如何告诉代理使用 HTTP 通信仍在使用连接?

How to tell a proxy a connection is still used using HTTP communication?

我有一个供人类使用的客户端 GUI 应用程序,它使用一些 SOAP Web 服务并使用 cURL 作为底层 HTTP 通信库。根据输入的不同,处理请求可能会花费大量时间,甚至一小时。客户端和服务器都不会因为这个原因自行超时,并且已经过测试并且可以正常工作。大多数请求都会在几分钟内得到处理,所以这是一个边缘案例。

我的一个用户被迫在我的客户端应用程序和我的服务器之间使用代理,并且出于各种原因无法控制它。该代理已配置超时,并在 4 分钟无数据传输后关闭与我的客户端的连接。因此用户可以(并且确实)上传数据,例如30 分钟后服务器开始处理数据,4 分钟后代理关闭连接,服务器将静默继续处理请求,但用户会留下一些错误消息并且不会得到处理结果。我的应用程序已经使用了 TCP Keep Alive,所以这应该不是问题,但超时似乎是为更高级别的数据定义的。它的工作原理与 squid 的选项 read_timeout 相同,我用它来重现我们内部设置中的行为。

我现在想做的是在我的 web 服务中启动一个后台线程,它在处理请求的所有时间里简单地向我的客户端输出一些垃圾数据,客户端忽略这些数据并告诉代理连接仍然有效。我可以使用用户代理识别我的客户端,并可以配置是否输出该数据或不输出服务器端等,因此使用 Web 服务的其他客户端不会遇到问题。

我想问的是,是否有任何符合 HTTP 的方法可以在实际 HTTP 响应之前输出此类垃圾数据?所以例如一遍又一遍地简单地输出 \r\n 而没有任何其他内容是否足以使 HTTP 与所有请求库兼容?或者甚至是二进制 0?或者一些完整的 HTTP headers 声明“真正的答案即将到来,请耐心等待”?根据我的调查,这听起来很像分块 HTTP 编码,但我不确定这是否适用。

我想要以下内容,其中所有那些“等待”的东西最后都被简单地忽略了,最后真正的 HTTP 响应包含 Content-Length 等等。

Wait...\r\n
Wait...\r\n
Wait...\r\n
[...]
HTTP/1.1 200 OK\r\n
Server: Apache/2.4.23 (Win64) mod_jk/1.2.41\r\n
[...]
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope[...]

这是否可以通过某种标准的 HTTP 方式实现?如果可以,我需要采用什么方法?谢谢!

HTTP Status 102

HTTP 状态 102 不正是我需要的吗?据我了解规范,我可以简单地一遍又一遍地打印该响应行,直到最终响应可用?

HTTP 状态 102 是 dead-end,有两件事可能会起作用,具体取决于所使用的代理:NPH script 可用于定期向客户端直接打印 headers。重要的是 NPH 脚本通常会绕过 Web 服务器的 header 缓冲区,因此可以根据需要通过网络传输。它们 "only" 需要正确的 HTTP headers 并且取决于网络服务器和代理,因此创建递增的、唯一的 headers 可能是个好主意。只需在 header 名称中添加一些计数器即可。

第二件事是 chunked transfer-encoding,在这种情况下,可以在响应 body 中将小块虚拟数据打印到客户端。好事是可以使用服务器端刷新等根据需要通过网络传输如此少量的数据,坏事是客户端接收此数据并且默认情况下表现得好像它是预期响应的一部分body。这当然可能会破坏应用程序,但大多数 HTTP 库都提供回调来处理接收到的数据,如果你打印一些独特的数据,客户端应该能够过滤掉垃圾。

在我的例子中,Web 服务正在生成一些后台线程,并且根据请求的服务的入口点,它使用 NPH 或数据块打印 headers。在这两种情况下,数据可以相同,因此 NPH-header 也可用于分块 transfer-encoding。

我的 NPH 解决方案不适用于 Squid,但分块的解决方案可以。 Squid 的问题是它的 read_timeout 设置根本不是连接接收数据的低级别,而是一些逻辑 HTTP 东西。这意味着 Squid 确实收到了我的 headers,但它期望在使用 read_timeout 定义的时间段内收到完整的 HTTP header。对于我的 NPH 方法,情况并非如此,仅仅是因为根据设计,我只想发送一些垃圾 headers 以忽略,直到真正的 headers 到达。

此外,必须注意 Apache httpd 中的 NPH,但在我的用例中它有效。我可以在 Squid 的日志中看到单独的 headers,并且在响应 body 等之后没有任何垃圾。避免使用 Action 指令。

Apache2 sends two HTTP headers with a mapped "nph-" CGI