How to enable HTTP range requests for non-static content in Apache?

516 views Asked by At

It looks like HTTP range requests are enabled by default in Apache and Nginx, but only for static content. How can one do the same for non-static content (e.g. dynamically generated by a CGI (PHP, Python...) script)? My attempts to find some documentation on the issue were all unsuccessful.

Bonus points for possible peculiarities when said Apache is proxied behind an Nginx server.

Compare this:

$ curl -v --range 0-1 http://localhost/index.html -o /dev/null 2>&1 | grep -e '[<>]'
> GET /index.html HTTP/1.1
> Host: localhost
> Range: bytes=0-1
> User-Agent: curl/7.81.0
> Accept: */*
>
< HTTP/1.1 206 Partial Content
< Date: Mon, 10 Jul 2023 13:59:30 GMT
< Server: Apache/2.4.52 (Ubuntu)
< Last-Modified: Tue, 04 Jul 2023 15:16:01 GMT
< ETag: "29af-5ffaac2d35ea6"
< Accept-Ranges: bytes
< Content-Length: 2
< Vary: Accept-Encoding
< Content-Range: bytes 0-1/10671
< Content-Type: text/html

with this:

$ curl -v --range 0-1 http://localhost/cgi-bin/testenv.pl -o /dev/null 2>&1 | grep -e '[<>]'
> GET /cgi-bin/testenv.pl HTTP/1.1
> Host: localhost
> Range: bytes=0-1
> User-Agent: curl/7.81.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Mon, 10 Jul 2023 14:00:08 GMT
< Server: Apache/2.4.52 (Ubuntu)
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html

Side note: The script is the classical for-loop over the ENV array. Interesting enough: when filtering the keys, in the case of one variable output Apache returns 206, for more than one it switches to 200.

1

There are 1 answers

1
dodrg On
< HTTP/1.1 206 Partial Content
...
< Accept-Ranges: bytes
< Content-Length: 2
...
< Content-Range: bytes 0-1/10671

If the output of your perl script will be more than 10671 bytes, you should see the the HTML status 206 Partital Content.

Relevant for the usage of the 206 Partitial Content mode is the necessity of having at least 2 chunks of partitial content to send. Else 200 OK will be used.

Responsible for the chunk size of the partitial content is the server variable HTTP_RANGE.

If your problem persists when using your "dynamic content" and the delivered size is more than the defined HTTP_RANGE, check the presence and content of HTTP_RANGE during the runtime of your script.

As a example:
For a PHP to tune the chunk size, I had to adjust it in the php file itself to define the desired size:

$_SERVER['HTTP_RANGE'] = "bytes:0-100485759";

In my case I had to "switch off" the 206 Partitial Content as the outdated php software did send the first chunk only in some cases. So, as a workaround, I defined the chunk size larger than the largest file until the update got available.