As part of the ZX Spectrum community I wrote a tool that can download content over HTTP from a ZX Spectrum Next, but one prerequisite is that the content-length header is present (so it operate properly).

A friend from the community runs a server and built a (really nice) GUI tool on top the .http command where users can find and download software for their Spectrum.

However, for reasons unknown, it wasn't working and content-length just seemed to be missing.

This fix isn't Speccy specific, it will fix missing content length for Apache 2 servers.

Testing

Even though the content-length was being set in the PHP files, by default, Apache was configured to chunk encoding (which is generally prefer, by the server, when sending dynamic based content, i.e. content generated by a PHP file).

So somewhere the content-length was being stripped.

This is all tested using a curl command with the -i flag to include headers:

$ curl -i example.com

Though this does include the full body, so it's easier to debug using -I (which requests the headers via a HEAD request) but the HEAD request is not equal to GET so we'll explicitly call a GET using -X:

$ curl -I -X GET example.com

Now we just have the headers and we can check if anything is missing.


Note that the information about browsers is completely wrong. I thought the header was being synthesised by the browser, but if you look carefully the header is in the raw response. I'm sure I saw it was being added, but I now suspect I was just confused whilst debugging. I've left this here in case it's at all useful, but keep in mind it's wrong!

<wrong-content>

A note about debugging with browser tools: browsers are going to augment the "raw" request. Firstly you have caching in play (so fire up the privacy window and disable caching from the network panel), but also they show you how they interpreted the headers.

This is Firefox for instance on https://www.google.com:

Firefox GET request headers panel

Whereas if we tick that "raw" checkbox, we can see the content-length was never part of the headers:

Firefox raw headers

Chrome will also add the header (with no option for the original response) but show it as a content length of zero.

</wrong-content>


So, make sure you're testing as close to the metal as possible.

Fixing

At some point (in Apache's history), a change was made to prevent scripts from setting certain headers (in particular content-length) to mitigate potential vulnerabilities.

So to trust your scripts, an apache rule is required to apply this. The follow example solved our particular problem, including the change in an .htaccess file in the root of the directory being served:

<Files *.php>
  SetEnv ap_trust_cgilike_cl 1
</Files>

Now Apache will trust all the headers, content-length specifically, from the PHP files.