HTTP pipelining in statistics channels do not work - browser hangs
Summary
Web browser hands for 30 seconds while loading XML statistics, and after a timeout it loads the page successfully. This is most likely caused by broken HTTP pipelining.
BIND version used
main - d48fa3b1
$ curl --version
curl 7.79.1 (x86_64-pc-linux-gnu) libcurl/7.79.1 OpenSSL/1.1.1l zlib/1.2.11 brotli/1.0.9 zstd/1.5.0 libidn2/2.3.2 libpsl/0.21.1 (+libidn2/2.3.0) libssh2/1.9.0 nghttp2/1.46.0
Release-Date: 2021-09-22
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets zstd
$ pacman -Q curl
curl 7.79.1-1
BIND branches 9.11 and 9.16 are not affected. A possible regression in !5455 (merged)?
Steps to reproduce
Request two URLs and use pipelining. cURL does this by default on my system:
$ curl -v -o /dev/null http://127.0.0.1:8888/bind9.xsl -o /dev/null http://127.0.0.1:8888/bind9.xsl
What is the current bug behavior?
First file is downloaded immediately and the second file just hangs until cURL times out.
$ curl -v -o /dev/null http://127.0.0.1:8888/bind9.xsl -o /dev/null http://127.0.0.1:8888/bind9.xsl
* Trying 127.0.0.1:8888...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 127.0.0.1 (127.0.0.1) port 8888 (#0)
> GET /bind9.xsl HTTP/1.1
> Host: 127.0.0.1:8888
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/xslt+xml
< Date: Wed, 03 Nov 2021 14:15:19 GMT
< Expires: Wed, 03 Nov 2021 14:15:19 GMT
< Last-Modified: Wed, 03 Nov 2021 14:12:44 GMT
< Cache-Control: public
< Server: libisc
< Content-Length: 38976
<
{ [7007 bytes data]
100 38976 100 38976 0 0 31.6M 0 --:--:-- --:--:-- --:--:-- 37.1M
* Connection #0 to host 127.0.0.1 left intact
* Found bundle for host 127.0.0.1: 0x5649e7d7a9a0 [serially]
* Can not multiplex, even if we wanted to!
* Re-using existing connection! (#0) with host 127.0.0.1
* Connected to 127.0.0.1 (127.0.0.1) port 8888 (#0)
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0> GET /bind9.xsl HTTP/1.1
> Host: 127.0.0.1:8888
> User-Agent: curl/7.79.1
> Accept: */*
>
0 0 0 0 0 0 0 0 --:--:-- 0:00:30 --:--:-- 0* Connection died, retrying a fresh connect (retry count: 1)
0 0 0 0 0 0 0 0 --:--:-- 0:00:30 --:--:-- 0
* Closing connection 0
* Issue another request to this URL: 'http://127.0.0.1:8888/bind9.xsl'
* Hostname 127.0.0.1 was found in DNS cache
* Trying 127.0.0.1:8888...
* Connected to 127.0.0.1 (127.0.0.1) port 8888 (#1)
> GET /bind9.xsl HTTP/1.1
> Host: 127.0.0.1:8888
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/xslt+xml
< Date: Wed, 03 Nov 2021 14:15:49 GMT
< Expires: Wed, 03 Nov 2021 14:15:49 GMT
< Last-Modified: Wed, 03 Nov 2021 14:12:44 GMT
< Cache-Control: public
< Server: libisc
< Content-Length: 38976
<
{ [7007 bytes data]
100 38976 100 38976 0 0 1298 0 0:00:30 0:00:30 --:--:-- 1298
* Connection #1 to host 127.0.0.1 left intact
What is the expected correct behavior?
HTTP Persistent Connections either correctly serve multiple requests, or are correctly terminated with Connection: close
HTTP header.
Relevant configuration files
statistics-channels {
inet 127.0.0.1 port 8888;
};
Relevant logs and/or screenshots
None.
Possible fixes
Either:
- Fix persistent HTTP connections in statistics channel
- Signal connection closure after each HTTP response (
Connection: close
header) - Downgrade to HTTP/1.0 which does not use persistent connections by default - we most likely don't need HTTP 1.1 features anyway.