PHP response to HEAD request
Asked Answered
D

3

8

I have a PHP script that serves portions of a PDF file by byte ranges.

If an HTTP HEAD request is received, it should send back headers (including the PDF file size) but not the actual file contents. I have tried this:

header('HTTP/1.1 200 OK');
header('Content-Type: application/pdf');
header('Accept-Ranges: bytes');
header('Content-Length: '.filesize($Pathname));
die;

The problem is that something (I assume the web server == LiteSpeed) replaces the Content-Length header with Content-Length: 0 - which defeats the whole purpose.

Can anyone suggest what I should be doing? Thanks

Descry answered 4/1, 2017 at 11:15 Comment(9)
Have you checked if the $Pathname is correct?Lanni
How do you know it is replaced?Prostomium
@Paul yes the $Pathname variable is definitely correct. I've also written to a log file that confirms that filesize($Pathname) is the actual file size.Descry
@BartFriederichs - by viewing network activity in Firefox (F12).Descry
try to add header('Dummy-Length: ' . filesize($Pathname)); and header('Dummy-Exists: ' . file_exists($Pathname));Enjoy
Tried that @IuriiDrozdov - Firefox toolbox reports Dummy-Length: 1545019 and Dummy-Exists: 1 (but also Content-Length: 0)Descry
please, specify in your question which webserver are you using, and also the head request madeTall
@leo_ap The server is LiteSpeed. There is no actual HEAD request sent; for testing, I've coded the PHP to assume it's a HEAD request if a byte-range is not requested.Descry
I have no idea of LiteSpeed but Content-Length tends to be mangled when you have some sort of transparent compression. You should also test a real HEAD request because otherwise you're trying to send incorrect data and the unexpected can happen.Teacart
E
6

From w3c Hypertext Transfer Protocol -- HTTP/1.1:

When a Content-Length is given in a message where a message-body is allowed, its field value MUST exactly match the number of OCTETs in the message-body. HTTP/1.1 user agents MUST notify the user when an invalid length is received and detected.

And:

The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET.

So, I suppose, your code will properly work if you send real HEAD request to your server.

Enjoy answered 4/1, 2017 at 12:25 Comment(4)
I can't see that a real HEAD request would make any difference, since the PHP response is independent of the inital request isn't it?Descry
"I can't see that a real HEAD request would make any difference" - I can. That firmly places the blame at the door of the webserver rather than on PHP or your code (assuming you get the same behaviour in response to a HEAD request).Ulises
@Descry just give it a try. You can use curl -i -D -I -X HEAD http:// yourserver.com (without space between http:// and domain name) or PostmanEnjoy
Thanks - and to @Ulises - you are right. Who would have believed that in order to respond to a HEAD request, you need a HEAD request? I feel a bit silly now.Descry
A
2

It's the webserver job, not yours.

In my case I left everything to the Apache webserver and nothing changed in my php code except of how the requests is being parsed

For example things like

if($_SERVER['REQUEST_METHOD'] === "GET"){
     //ok
}else{
     //send 400 Bad Request
}

are changed to

if($_SERVER['REQUEST_METHOD'] === "GET" || $_SERVER['REQUEST_METHOD'] === "HEAD"){
     //ok
}else{
     //send 400 Bad Request
}

and Apache did all the heavy lifting (striped the response body).

(don't try to ob_clean() or die("") or things like this).

related resources:

http://hc.apache.org/httpclient-3.x/methods/head.html

https://security.stackexchange.com/questions/62811/should-i-disable-http-head-requests

Apache 2.2.2 response on HEAD requests

Amplexicaul answered 8/8, 2018 at 2:50 Comment(0)
O
0

As Lurii mentioned, the content length is affected by your request type.

With GET requests, a non-matching content length may result in a hanging client, so LiteSpeed will verify the content length before sending the header to the client.

Using a HEAD request should return the content length as expected.

Overmantel answered 4/1, 2017 at 19:53 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.