delphi 使用TidHTTP的POST在检索JSON响应时挂起

jei2mxaa  于 2023-01-30  发布在  其他
关注(0)|答案(2)|浏览(318)

这个问题可能更多的是一个提示,让人们搜索解决方案,如果他们有同样的问题(因为我最终找到了解决方案)。
我有一个应用程序,它通过本地服务器(请求/响应主体中混合了GET/POST和JSON内容)执行一些HTTP请求。服务器是第三方应用程序,在我将其升级到最新版本后,我的Delphi应用程序不再工作。结果发现它现在挂在语句上:

IdHTTP.Post("URL", "Payload", "BytesStreamResult");

由于手动的POSTMAN请求仍然有效,因此它必须位于Delphi客户端。
进一步隔离该问题表明,HTTP POST请求确实获得了具有有效HTTP响应标头的HTTP 200响应,但随后在读取响应正文时卡住。

IOHandler.ReadLn

当我将报头与POSTMAN响应进行比较时,我注意到"Transfer-Encoding:在 Delphi React中缺失了"chunked"。
最后,我注意到与TIdHTTPhoKeepOrigProtocol选项相关的代码,默认情况下没有设置该选项,因此,我的POST请求被"降级"为HTTP 1.0请求,我猜这会使(更新后的)服务器做出不同的响应(我不是RFCMaven,但我猜"chunked"可能只是HTTP 1.1选项)。
设置了这个选项之后,一切都和以前一样了(实际上,响应现在在Delphi中读作"chunked")。
总结:

  1. hoKeepOrigProtocol不应该是默认选项吗?(为什么要惩罚那些不好的公民呢?)
    1.我们可以拦截这个吗?现在我的POST假设一个流响应,因此它挂起,因为服务器没有写入任何东西到缓冲区。高级代码看起来像什么?因为它看起来是解释头响应头,然后决定是否需要更多的响应读取的混合体。
    (it我也没有做任何关于超时的具体操作。我的印象是它会永远挂起,或者至少超过10分钟...)
b1payxdu

b1payxdu1#

TIdHTTP支持非分块响应(是的,这是HTTP 1.1的一个特性),因此挂起可能是由于服务器发送了格式错误的响应(应该向服务器作者报告这个bug)。
当阅读一个 non-chunkednon-MIME 响应时,TIdHTTP * 并不像你所说的那样 * 使用IOHandler.ReadLn来读取响应的主体。
但是,由于您没有显示响应实际上是什么样子的,所以没有人能够确切地解释为什么会发生挂起。
hoKeepOrigProtocol不应该是默认选项吗?
在第一次引入这个选项的时候,没有。周围有很多有缺陷的HTTP 1.1服务器,降级到HTTP 1.0是有道理的。
不过那是很多年前的事了,如今HTTP 1. 1成熟多了,这样有bug的服务器已经很少了。所以,如果您觉得应该更改默认行为,请随时向Indy's GitHub repo提交更改/拉取请求。
我们能拦截吗?
不可以。您描述的行为很可能是由HTTP服务器中的错误引起的。它可能没有发送所有应该发送的数据,或者响应可能格式错误,导致TIdHTTP预期发送的数据多于实际发送的数据。无论是哪种情况,您所能做的就是为TIdHTTP分配一个非无限的超时。
它也没有做任何关于超时的具体事情。我的印象是它会永远挂起,或者至少挂10分钟以上。
Indy的设计默认使用无限超时,您可以为TIdHTTPConnectTimeoutReadTimeout属性分配自定义超时。

mv1qrgav

mv1qrgav2#

设置此选项可防止HTTP协议降级:

IdHTTP.HTTPOptions := IdHTTP.HTTPOptions + [hoKeepOrigProtocol];

当然,这取决于服务器如何处理协议规范,以及是否会导致问题。

相关问题