Delphi 7 中的 Indy 错误:未声明的标识符:'hoWantProtocolErrorContent'

Indy error in Delphi 7: Undeclared identifier: 'hoWantProtocolErrorContent'

当使用 TIdHTTP 发送带有 JSON 变量的 GET 命令时,有时服务器 returns 会出现以下错误:

HTTP/1.1 500 Internal Server Error

使用 Insomnia 测试 JSON 结果,我看到了完整的 JSON 响应和一个漂亮的响应,清楚地表明了问题所在。我真的需要填写 TStringStream,即使响应代码不是 200。

经过大量搜索,我明白我应该使用 HTTPOptions 和参数:hoNoProtocolErrorExceptionhoWantProtocolErrorContent。但是,当使用 hoWantProtocolErrorContent 选项时,出现以下错误:

Undeclared identifier: 'hoWantProtocolErrorContent'

您使用的是旧版本的 Indy(是 Delphi 7 附带的版本吗?)。 Delphi 7 于 2002 年发布,而 hoWantProtocolErrorContent 标志于 2016 年引入。根据 New TIdHTTP flags and OnChunkReceived event in Indy's blog):

hoWantProtocolErrorContent: when an HTTP error response is received, TIdHTTP normally reads and discards the response’s message body and then raises EIdHTTPProtocolException (the message body is available in the EIdHTTPProtocolException.ErrorMessage property). If the hoNoProtocolErrorException flag is enabled, or the ResponseCode number is specified in the request's AIgnoreReplies parameter, then no EIdHTTPProtocolException is raised, as the caller would like to process the ResponseCode manually. Normally TIdHTTP would still discard the message body, though. If this new flag is enabled, the message body will no longer be discarded, it will be saved in the caller's target TStream like a successful response would be. This flag is disabled by default to preserve existing behavior to discard error message bodies.

因此,如果没有 hoWantProtocolErrorContent 标志,访问 HTTP 错误响应正文数据的唯一方法是禁用 hoNoProtocolErrorException 标志(默认情况下禁用),然后捕获引发的 EIdHTTPProtocolException 异常并读取其 ErrorMessage 属性,例如:

var
  Response: TStringStream;

Response := TStringStream.Create('');
try
  try
    IdHTTP1.Get(url, Response);
  except
    on E: EIdHTTPProtocolException do
      WriteStringToStream(Response, E.ErrorMessage);
  end;
  // use Response.DataString as needed...
finally
  Response.Free;
end;

或更简单:

var
  Response: string;

try
  Response := IdHTTP1.Get(url);
except
  on E: EIdHTTPProtocolException do
    Response := E.ErrorMessage;
end;
// use Response as needed...