TRestRequest.Execute 当响应代码为 300 或更高时退出线程
TRestRequest.Execute exits thread when responses code is 300 or higher
我需要检查来自 RestResponse
的特定状态代码,但是 RestRequest.Execute
似乎在状态代码不是 200 时生成 EHTTPProtocolException
。
我无法理解为什么 EHTTPProtocolException
会被引发。我怎样才能忽略它或压制它?我确实检查了它是否只是调试器,但即使在发布版本中以及 运行 独立时,代码也会在执行时停止。
我的代码如下:
procedure TdmWebsockets.GetRustMapURL(const Connection: TsgcWSConnection; const Data: string);
begin
var jdata := TJSONObject.ParseJSONValue(Data);
var restClient := TRESTClient.Create(Self);
var restResponse := TRESTResponse.Create(Self);
var restRequest := TRESTRequest.Create(Self);
try
var isStaging := jdata.GetValue<Boolean>('data.staging');
var isBarren := jdata.GetValue<Boolean>('data.barren');
var seed := jdata.GetValue<Int32>('data.seed');
var size := jdata.GetValue<Int32>('data.size');
restRequest.Client := restClient;
restRequest.Response := restResponse;
restClient.BaseURL := 'https://rustmaps.com/api/v2/maps/' + seed.ToString + '/' + size.ToString;
restClient.RaiseExceptionOn500 := False;
restRequest.AddParameter('staging', BoolToStr(isStaging, True));
restRequest.AddParameter('barren', BoolToStr(isBarren, True));
restRequest.Params.AddHeader('X-API-Key', 'REDACTED');
restRequest.Method := TRESTRequestMethod.rmPOST;
Writeln('before');
restRequest.Execute;
Writeln('after');
var Writer: TJsonTextWriter;
var StringWriter: TStringWriter;
try
StringWriter := TStringWriter.Create();
Writer := TJsonTextWriter.Create(StringWriter);
Writer.Formatting := TJsonFormatting.Indented;
Writer.WriteStartObject;
/////////////////////////////////////////////
Writer.WritePropertyName('command');
Writer.WriteValue(COMMAND_GETMAP);
/////////////////////////////////////////////
if restResponse.Status.SuccessOK_200 or restResponse.Status.ClientErrorDuplicate_409 then
begin
Writeln('200 ok');
Writer.WritePropertyName('success');
Writer.WriteValue(True);
/////////////////////////////////////////////
var mapID := restResponse.JSONValue.GetValue<string>('mapId');
Writer.WritePropertyName('mapID');
Writer.WriteValue(mapID);
/////////////////////////////////////////////
end
else if restResponse.Status.ClientErrorBadRequest_400 then
begin
Writeln('400 ok');
/////////////////////////////////////////////
Writer.WritePropertyName('success');
Writer.WriteValue(False);
/////////////////////////////////////////////
var reason := restResponse.JSONValue.GetValue<string>('reason');
Writer.WritePropertyName('reason');
Writer.WriteValue(reason);
/////////////////////////////////////////////
end;
Writer.WriteEndObject;
Writeln(StringWriter.ToString);
Connection.WriteData(StringWriter.ToString);
finally
StringWriter.Free;
Writer.Free;
end;
finally
restRequest.Free;
restResponse.Free;
restClient.Free;
jdata.Free;
end;
end;
编辑:
当单击异常 window 上的“中断”按钮时,它会将我带到 Rest.HttpClient
中的 Execute
方法,尽管它没有被添加到使用中。步进显示它在 Rest.HttpClient
中执行,而不是在 Rest.Client
.
中执行
当尝试使用 try .. except
时,我需要 Rest.HttpClient
来获取异常类型 EHTTPProtocolException
。使用 try .. except
时它仍然会抛出异常。我知道调试器仍会捕获它,但代码永远不会在 try .. except
中运行,只会在异常抛出后停止。
IF 异常正在转义 TRestRequest.Execute()
到您的代码中,然后用 try..except
捕获它。 EHTTPProtocolException
有一个 ErrorCode
属性 你可以看看,如果需要的话。
A try..except
根本不会阻止引发异常。调试器仍会显示引发的异常,除非您将调试器配置为忽略它。但是您的代码将能够 捕获 异常并根据需要进行处理。如果调试器因异常而中断,只需按 IDE 上的“运行”按钮或键盘上的 F9 即可继续执行,并且异常将传递给代码中最近的匹配异常处理程序。
例如:
try
restRequest.Execute;
except
// swallow ALL exceptions...
end;
继续前进,无需更新 uses
子句 - 除非您希望代码忽略非 EHTTPProtocolException
异常并让它们向上传播调用堆栈(如您所愿) ,在这种情况下,您可以改用它:
uses
..., REST.HttpClient;
try
restRequest.Execute;
except
on E: Exception do begin
if not (E is EHTTPProtocolException) then begin
// DON'T swallow unknown non-HTTP errors...
raise;
end;
// swallow HTTP errors and let subsequent code check the status...
end;
end;
或:
uses
..., REST.HttpClient;
try
restRequest.Execute;
except
on E: EHTTPProtocolException do begin
// swallow HTTP errors and let subsequent code check the status...
end;
on E: Exception do begin
// DON'T swallow unknown non-HTTP errors...
raise;
end;
end;
或:
uses
..., REST.HttpClient;
try
restRequest.Execute;
except
on E: EHTTPProtocolException do;
// swallow only HTTP errors and let subsequent code check the status...
end;
但是,IF 异常没有转义 TRestRequest.Execute()
到您的代码中,那么这个问题就没有实际意义了。异常将在 Execute()
内部处理,根本不需要在您的代码中使用 try..except
。如果您不想在调试代码时看到异常,那么只需 configure the debugger to ignore EHTTPProtocolException
并继续。
我误解了问题是什么,我关注的是抛出的 HTTPException 而不是真正的问题。似乎因为我的应用程序是一个控制台应用程序,并且 sgcWebsockets 中的线程的 NotifyEvent 是 noSync,所以每次调用 TCustomRESTClient.HandleEvent
时线程都会退出。在这种情况下,它被调用并实际通过,因为 restRequest.SynchronizedEvents
默认设置为 true 但应该为 false。
所以解决方案就是简单地做:
restRequest.SynchronizedEvents := False;
我需要检查来自 RestResponse
的特定状态代码,但是 RestRequest.Execute
似乎在状态代码不是 200 时生成 EHTTPProtocolException
。
我无法理解为什么 EHTTPProtocolException
会被引发。我怎样才能忽略它或压制它?我确实检查了它是否只是调试器,但即使在发布版本中以及 运行 独立时,代码也会在执行时停止。
我的代码如下:
procedure TdmWebsockets.GetRustMapURL(const Connection: TsgcWSConnection; const Data: string);
begin
var jdata := TJSONObject.ParseJSONValue(Data);
var restClient := TRESTClient.Create(Self);
var restResponse := TRESTResponse.Create(Self);
var restRequest := TRESTRequest.Create(Self);
try
var isStaging := jdata.GetValue<Boolean>('data.staging');
var isBarren := jdata.GetValue<Boolean>('data.barren');
var seed := jdata.GetValue<Int32>('data.seed');
var size := jdata.GetValue<Int32>('data.size');
restRequest.Client := restClient;
restRequest.Response := restResponse;
restClient.BaseURL := 'https://rustmaps.com/api/v2/maps/' + seed.ToString + '/' + size.ToString;
restClient.RaiseExceptionOn500 := False;
restRequest.AddParameter('staging', BoolToStr(isStaging, True));
restRequest.AddParameter('barren', BoolToStr(isBarren, True));
restRequest.Params.AddHeader('X-API-Key', 'REDACTED');
restRequest.Method := TRESTRequestMethod.rmPOST;
Writeln('before');
restRequest.Execute;
Writeln('after');
var Writer: TJsonTextWriter;
var StringWriter: TStringWriter;
try
StringWriter := TStringWriter.Create();
Writer := TJsonTextWriter.Create(StringWriter);
Writer.Formatting := TJsonFormatting.Indented;
Writer.WriteStartObject;
/////////////////////////////////////////////
Writer.WritePropertyName('command');
Writer.WriteValue(COMMAND_GETMAP);
/////////////////////////////////////////////
if restResponse.Status.SuccessOK_200 or restResponse.Status.ClientErrorDuplicate_409 then
begin
Writeln('200 ok');
Writer.WritePropertyName('success');
Writer.WriteValue(True);
/////////////////////////////////////////////
var mapID := restResponse.JSONValue.GetValue<string>('mapId');
Writer.WritePropertyName('mapID');
Writer.WriteValue(mapID);
/////////////////////////////////////////////
end
else if restResponse.Status.ClientErrorBadRequest_400 then
begin
Writeln('400 ok');
/////////////////////////////////////////////
Writer.WritePropertyName('success');
Writer.WriteValue(False);
/////////////////////////////////////////////
var reason := restResponse.JSONValue.GetValue<string>('reason');
Writer.WritePropertyName('reason');
Writer.WriteValue(reason);
/////////////////////////////////////////////
end;
Writer.WriteEndObject;
Writeln(StringWriter.ToString);
Connection.WriteData(StringWriter.ToString);
finally
StringWriter.Free;
Writer.Free;
end;
finally
restRequest.Free;
restResponse.Free;
restClient.Free;
jdata.Free;
end;
end;
编辑:
当单击异常 window 上的“中断”按钮时,它会将我带到 Rest.HttpClient
中的 Execute
方法,尽管它没有被添加到使用中。步进显示它在 Rest.HttpClient
中执行,而不是在 Rest.Client
.
当尝试使用 try .. except
时,我需要 Rest.HttpClient
来获取异常类型 EHTTPProtocolException
。使用 try .. except
时它仍然会抛出异常。我知道调试器仍会捕获它,但代码永远不会在 try .. except
中运行,只会在异常抛出后停止。
IF 异常正在转义 TRestRequest.Execute()
到您的代码中,然后用 try..except
捕获它。 EHTTPProtocolException
有一个 ErrorCode
属性 你可以看看,如果需要的话。
A try..except
根本不会阻止引发异常。调试器仍会显示引发的异常,除非您将调试器配置为忽略它。但是您的代码将能够 捕获 异常并根据需要进行处理。如果调试器因异常而中断,只需按 IDE 上的“运行”按钮或键盘上的 F9 即可继续执行,并且异常将传递给代码中最近的匹配异常处理程序。
例如:
try
restRequest.Execute;
except
// swallow ALL exceptions...
end;
继续前进,无需更新 uses
子句 - 除非您希望代码忽略非 EHTTPProtocolException
异常并让它们向上传播调用堆栈(如您所愿) ,在这种情况下,您可以改用它:
uses
..., REST.HttpClient;
try
restRequest.Execute;
except
on E: Exception do begin
if not (E is EHTTPProtocolException) then begin
// DON'T swallow unknown non-HTTP errors...
raise;
end;
// swallow HTTP errors and let subsequent code check the status...
end;
end;
或:
uses
..., REST.HttpClient;
try
restRequest.Execute;
except
on E: EHTTPProtocolException do begin
// swallow HTTP errors and let subsequent code check the status...
end;
on E: Exception do begin
// DON'T swallow unknown non-HTTP errors...
raise;
end;
end;
或:
uses
..., REST.HttpClient;
try
restRequest.Execute;
except
on E: EHTTPProtocolException do;
// swallow only HTTP errors and let subsequent code check the status...
end;
但是,IF 异常没有转义 TRestRequest.Execute()
到您的代码中,那么这个问题就没有实际意义了。异常将在 Execute()
内部处理,根本不需要在您的代码中使用 try..except
。如果您不想在调试代码时看到异常,那么只需 configure the debugger to ignore EHTTPProtocolException
并继续。
我误解了问题是什么,我关注的是抛出的 HTTPException 而不是真正的问题。似乎因为我的应用程序是一个控制台应用程序,并且 sgcWebsockets 中的线程的 NotifyEvent 是 noSync,所以每次调用 TCustomRESTClient.HandleEvent
时线程都会退出。在这种情况下,它被调用并实际通过,因为 restRequest.SynchronizedEvents
默认设置为 true 但应该为 false。
所以解决方案就是简单地做:
restRequest.SynchronizedEvents := False;