【发布时间】:2023-01-26 23:15:00
【问题描述】:
如果人们遇到相同的问题(因为我最终找到了解决方案),这个问题可能更像是一个提示,供人们搜索解决方案。
我有一个使用本地服务器执行一些 HTTP 请求的应用程序(在请求/响应主体中混合使用 GET/POST 和 JSON 内容)。服务器是第三方应用程序,在我将其升级到最新版本后,我的 Delphi 应用程序不再运行。 原来现在挂在语句上:
IdHTTP.Post("URL", "Payload", "BytesStreamResult");
由于手动 POSTMAN 请求仍在工作,它必须在 Delphi 客户端上。
进一步隔离问题表明,HTTP POST 请求确实获得了带有有效 HTTP 响应标头的 HTTP 200 响应,但随后在读取响应正文时卡住了。它挂在:
IOHandler.ReadLn
当我将标头与 POSTMAN 响应进行比较时,我注意到 Delphi 响应中缺少“Transfer-Encoding: chunked”。
最后,我注意到与TIdHTTP的hoKeepOrigProtocol选项相关的代码,默认情况下没有设置。
所以,我的 POST 请求被“降级”为 HTTP 1.0 请求,我想这现在使(更新的)服务器做出不同的响应(我不是 RFC 专家,但我猜“分块”可能是 HTTP 1.1 选项只要)。
设置此选项后,一切都像以前一样工作(实际上,响应现在在 Delphi 中被读取为“分块”)。
概括:
-
hoKeepOrigProtocol不应该是默认选项吗? (为什么要惩罚那些不是好公民的……) - 我们可以拦截这个吗?现在我的 POST 假设预先有一个流式响应,因此它挂起,因为服务器没有向缓冲区写入任何内容。
高级代码是什么样的?因为它似乎是解释标头响应标头然后决定是否需要更多响应读取的混合体。
(它也没有做任何关于超时的具体事情。我的印象是它永远挂起,或者至少 > 10 分钟......)
【问题讨论】:
-
TIdHTTP 支持非分块响应,因此挂起必须由服务器发送格式错误的响应引起(应该向服务器作者报告的错误)。 TIdHTTP 在读取响应正文时不使用
ReadLn,仅使用响应标头。但是由于您没有显示响应的实际情况,因此没有人可以确切地解释为什么会发生挂起。