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
重定向,或收到启用 hoTreat302Like303
的 302
重定向,则 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
,而不是相反。
对不起我的英语。
在 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
重定向,或收到启用 hoTreat302Like303
的 302
重定向,则 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
,而不是相反。