HttpWebRequest 在重定向时使用 GET 而不是像 idHttp 那样的 POST

HttpWebRequest using GET on redirect instead of POST like idHttp

对不起我的英语。

在 Delphi 中,我有一个激活了 hoWaitForUnexpectedData 选项的 idHttp 组件。

当我向 URL 发送 POST 请求时,它会将客户端重定向到具有相同 POST 请求和 header 的第二个 URL秒。此外,服务器响应在其 header.

中包含 "Connection: keep-alive"

但是,当我尝试在 C# 中使用 HttpWebRequest 组件执行相同的请求时,它使用 GET 方法重定向到第二个 URL。

我需要 C# HttpWebRequest 组件像 Delphi idHTTP 那样工作。我不明白为什么它在重定向后使用 GET 而不是 POST。

这是我在 Delphi 中使用 hoWaitForUnexpectedData 的代码:

  // The server is supposed to send a 'Content-Length' header without sending
  // the actual data. 1xx, 204, and 304 replies are not supposed to contain
  // entity bodies, either...
  if TextIsSame(ARequest.Method, Id_HTTPMethodHead) or
     TextIsSame(ARequest.MethodOverride, Id_HTTPMethodHead) or
     ((AResponse.ResponseCode div 100) = 1) or
     (AResponse.ResponseCode = 204) or
     (AResponse.ResponseCode = 304) then
  begin
    // Have noticed one case where a non-conforming server did send an
    // entity body in response to a HEAD request.  If requested, ignore
    // anything the server may send by accident
    if not (hoWaitForUnexpectedData in FOptions) then begin
      Exit;
    end;
    Result := CheckForPendingData(100);
  end
  else if (AResponse.ResponseCode div 100) = 3 then
  begin
    // This is a workaround for buggy HTTP 1.1 servers which
    // does not return any body with 302 response code
    Result := CheckForPendingData(5000);
  end else begin
    Result := True;
  end;

根据标准的定义,HTTP 重定向应该使用 GET 处理。因此,如果您发送 POST 并获得重定向作为答复,则预期的行为是对重定向地址执行 GET。我怀疑旧的 Delphi 组件遵循旧做法并复制调用,包括 POST 动词。

我会尝试在 HttpWebRequest 对象中禁用 AllowAutoRedirect 并手动处理它,因为您的情况似乎与标准不同。

hoWaitForUnexpectedData 选项对 TIdHTTP 处理重定向的方式没有影响,您引用的代码部分也没有影响。

但是,hoTreat302Like303 选项会影响重定向处理。如果 TIdHTTP 收到 303 重定向,或收到启用 hoTreat302Like303302 重定向,则 TIdHTTP 将新请求发送为 GET。否则,它使用与重定向请求相同的动词发送新请求。这是设计使然,TIdHTTPProtocol.ProcessResponse() 方法的实现代码中有一系列注释解释了此行为背后的合理性:

  // GDG 21/11/2003. If it's a 303, we should do a get this time

  // RLebeau 7/15/2004 - do a GET on 302 as well, as mentioned in RFC 2616

  // RLebeau 1/11/2008 - turns out both situations are WRONG! RFCs 2068 and
  // 2616 specifically state that changing the method to GET in response
  // to 302 and 303 is errorneous.  Indy 9 did it right by reusing the
  // original method and source again and only changing the URL, so lets
  // revert back to that same behavior!

  // RLebeau 12/28/2012 - one more time. RFCs 2068 and 2616 actually say that
  // changing the method in response to 302 is erroneous, but changing the
  // method to GET in response to 303 is intentional and why 303 was introduced
  // in the first place. Erroneous clients treat 302 as 303, though.  Now
  // encountering servers that actually expect this 303 behavior, so we have
  // to enable it again! Adding an optional HTTPOption flag so clients can
  // enable the erroneous 302 behavior if they really need it.

它的要点是 HTTP 规范说要为 303 重定向发送 GET,而是否为 [=16] 发送 GET 是不明确的=].有些浏览器会,有些不会。这就是添加 hoTreat302Like303 选项的原因,尽管它在默认情况下被禁用以向后兼容早期的 Indy 版本。

因此,您描述的行为意味着您一定遇到了 302 重定向,hoTreat302Like303 已禁用(这是默认设置)。如果启用该选项,TIdHTTP 将更像 HttpWebRequest,而不是相反。