我有一个用 Perl 编写的小型 CGI 脚本,它以 1 秒的间隔打印从 1 到 10 的数字:
root@debian-s-1vcpu-1gb-fra1-01:~# cat /usr/lib/cgi-bin/test
#!/usr/bin/perl
use strict;
local $|=1;
print "Content-encoding: none\nContent-type: text/plain\n\n";
#print "Content-type: text/plain\n\n";
for ( my $i = 1 ; $i <= 10 ; $i++ ) {
print "$i\n";
sleep(1);
}
root@debian-s-1vcpu-1gb-fra1-01:~#
该脚本在使用时按预期工作curl
:
但是,对于 Web 浏览器(例如 Chromium 88.0.4324.182 或 Firefox 78.13.0esr),页面加载 10 秒,然后立即显示从 1 到 10 的数字。Web 浏览器的请求和响应标头如下所示:
即使我使用与上面示例curl
相同的请求标头执行Firefox
,数字也会以 1 秒的间隔打印,因为它们应该:
$ curl -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Accept-Encoding:
gzip, deflate' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' -H 'Host: 164.90.236.255' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0' -v http://164.90.236.255/cgi-bin/test
* Expire in 0 ms for 6 (transfer 0x55b238016fb0)
* Trying 164.90.236.255...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55b238016fb0)
* Connected to 164.90.236.255 (164.90.236.255) port 80 (#0)
> GET /cgi-bin/test HTTP/1.1
> Host: 164.90.236.255
> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
> Accept-Encoding: gzip, deflate
> Accept-Language: en-US,en;q=0.5
> Connection: keep-alive
> Upgrade-Insecure-Requests: 1
> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
>
< HTTP/1.1 200 OK
< Date: Mon, 24 Jan 2022 12:19:56 GMT
< Server: Apache/2.4.25 (Debian)
< Content-encoding: none
< Keep-Alive: timeout=5, max=100
< Connection: Keep-Alive
< Transfer-Encoding: chunked
< Content-Type: text/plain
<
1
2
3
4
5
6
7
8
9
10
* Connection #0 to host 164.90.236.255 left intact
$
服务器已Apache 2.4.25
禁用mod_deflate
。
什么可能导致这种行为?如何在 Web 浏览器中禁用 CGI 脚本缓冲?也许有一个响应头允许人们控制这种行为。
您要查找的内容通常是通过 Ajax 完成的。Web 浏览器不会按照您希望的方式运行,因为想象一个非常复杂的 HTML/JS/CSS 页面,您需要渲染 10 次而不是一次。浏览器无法提前知道服务器将要发送什么数据,因此它们会尽量减少工作量以节省 CPU 周期。