Send HTTP headers before or after a cookie header? - php

I was wondering if there are any problems or difference between sending normal headers before or after sending cookie headers. Do some browsers prefer a certain order to headers? If the cookie header is to large would subsequent headers never be parsed?
setcookie("TestCookie", $value);
header("Content-type: text/javascript");
or
header('Location: http://www.example.com/');
setcookie("TestCookie", $value);
or
setcookie("SuperLargeCookie", $massive_value);
setcookie("TinyCookie", $small_value);
header("Status: 404 Not Found");

There is no difference. The Http protocol does not specify that headers are to be in a certain order. Browsers do not differentiate based on the order of headers either.
The total length of Http headers does have a limit. This limit is imposed by the server and not the browser. Typically between 8K and 16K. However this is configurable.

It really doesn't matter as long as the other HTTP headers have not been sent. setcookie() actually writes a header itself:
Set-Cookie: SuperLargeCookie=whatever; Max-Age=3600; Version=1
similar to a header() call:
Location: http://www.example.com/redirect

HTTP messages span packets all the time, so you'd be hard-pressed to overfill one unless you're jamming tons of kilobytes in there. If you need to do that, consider a better design. Browsers don't care about the order of headers since different servers (and applications) append headers all the time. Cookies are implemented as HTTP headers, so they should appear like so in the HTTP request:
Cookie: TestCookie=value\r\n
Content-type: text/javascript\r\n
\r\n
I'm not sure what the Status header is supposed to do in your example, but I don't think it's right since the webserver will set a 200 OK response code if the code executes correctly... The header function page has this examaple:
<?php
header("HTTP/1.0 404 Not Found");
?>
With the PHP header function, just make sure you're not writing any text out before issuing it. Otherwise, you could mess everything up.

Related

why does 'location' header field redirects immediately and other header fields don't when used with header() function in php

According to the PHP Manual
header() — Send a raw HTTP header
Now,
when I use following code :
header('location:form.html');
then, the header function immediately redirects the browser to form.html OR simply an HTTP response header is sent immediately after the execution of above line.
but when I use same header function to add some other header fields to the response header, for example:
header("X-Sample-Test: foo");
header('Content-type: text/plain');
then why doesn't it send an HTTP response header immediately?
First of all, correct me if I am wrong and secondly please do share more information on HTTP headers.
As was alluded to in a comment, the PHP.net documentation states that:
The second special case is the "Location:" header. Not only does it send this header back to the browser, but it also returns a REDIRECT (302) status code to the browser unless the 201 or a 3xx status code has already been set.1.
Thus that header is a special case.
but when I use same header function to add some other header fields to the response header
header("X-Sample-Test: foo");
header('Content-type: text/plain');
then why don't it sends a HTTP response header immediately.
It still sends those headers (you should be able to see them in a browser console - e.g. In a networking tab) but the browser doesn't send the user to a different URL like it does for a redirect header.
Take a look at the image below, where I inspected the response headers in the network tab after loading a PHP page with those headers. I highlighted those headers coming through. For more information about viewing headers see these answers for Google Chrome or Mozilla Firefox.
You may find it interesting to read some of the (positive-voted) user contributed notes on that documentation page.
1http://php.net/manual/en/function.header.php

PHP response to HEAD request

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
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.
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
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.

php setcookie behavior with cookies disabled

can anyone confirm the behavior of PHP's setcookie() function when the client has cookies disabled? According to the documentation:
"If output exists prior to calling this function, setcookie() will fail and return FALSE. If setcookie() successfully runs, it will return TRUE. This does not indicate whether the user accepted the cookie."
I'm not sure what 'successfully runs' means exactly, but this leads me to believe that the implementation doesn't care about whether the client accepts the cookie, and that we shouldn't have to worry about PHP errors / warnings related to the cookie actually being set or not. Is that right?
Thanks in advance
Cookies are sent via http header. Headers can ALWAYS be sent. Whether they're accepted/ignored is irrelevant - you can send ANY header you want.
The only way to tell if a client has accepted a cookie is if the cookie gets sent BACK to the server by the client on its NEXT request.
The only way setcookie() fails is if output has already started. That causes the PHP "headers already sent" warning.
e.g. A normal HTTP server->client response looks like this:
HTTP/1.1 200 OK
Content-type: text/html
Cookie: ...cookie data here ...
<html><body>Hi mom!</body></html>
But if you do output first, BEFORE calling setcookie, you'd end up with something like this:
HTTP/1.1 200 OK
Content-type: text/html
<html><body>Hi mom!</body></html>
Cookie: ... cookie data here ...
which doesn't work. Headers are only headers when they're in the header block of the response. If they show up in the body, they're not a header - they're part of the content. That's why PHP issues the "headers already sent", and doesn't send the cookie. It can't - the train has already left the station.
No. setcookie() passes a Set-Cookie HTTP header to the webserver, which in turn transfers it to the client.
Any warning pertaining to the header is an issue of your code structure. See also: How to fix "Headers already sent" error in PHP
The result code of setcookie() does not indicate if the client honors the Set-Cookie HTTP header however. Because neither PHP nor the webserver knows.
Quite correct, the server cannot detect the clients settings, you should verify this with your own implementation.
If you send a cookie upon first request, checking if it exists on the next request. Then you would know if the client excepts cookies or not. When that isn't the case you only have the IP and browser headers to tell you it could be the same user.
The next request can either be a new page request or for example an Ajax request that also sends headers and thus including cookies (if the browser excepts this).
If you attach a unique identifier to the new request uri and get an empty cookie response from him or her, you know the browser does not except cookies.

PHP - How do I send a 200 code response to a request and also forward it?

I am integrating another companies services with ours and they want to send an xml post request to us and get an 200 response with xml, but then I also need to forward the request.
Their user gets sent to our site when they click on a link on their page, which sends an xml post request to us. We are supposed to send an xml response back, and then forward the user to our home page.
I have figured out one or the other, but not both by setting headers.
For the 200 response:
header("Content-type: text/xml");
header("HTTP/1.1 200 OK");
header("Status: 200");
echo 'my-xml';
exit;
For the forward:
header("Location: http://www.example.com/");
exit;
But I can't figure out how to do both?
Also, this is being done in Wordpress by intercepting the pre_get_posts filter, which works fine.
You can't do this purely in HTTP headers. Executing header("Location: http://www.example.com/"); causes PHP to do an implicit Status: 302 response, and the output before the header() call will also trigger a Warning.
Also, since you're sending XML to the browser, and not HTML, there is no other mechanism that can perform the redirect. Either you're misunderstanding the requirement you've been given, or the API you're integrating with is asking you to do something impossible.

PHP cookie handling

A centain web client that I need to support, is sending back the Cookies header to my application twice in the HTTP headers, this in turn is making PHP unable to read the correct value for the cookie thus ignoring the session.
Here is the relevant part of the request I am seeing:
GET / HTTP/1.1
Cache-Control: max-age=0
Accept-Language: en-US
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a
Connection: Keep-Alive
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a
[...] Other irrelevant headers
I have two questions:
Is that a PHP bug? or is the behavior undefined when the client sends that same header twice?
Is there a quick workaround to make things work without having to manually parse the HTTP headers so I can read the right value of the cookie (and session) in my application? Or should I manually parse the HTTP header to set the session to its correct value?
According to the HTTP spec, a double header simply concatenates the values together with a comma, making it:
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a, PHPSESSID=49af82ddf12740e6a35b15985e93d91a
PHP should be able to parse the cookies, but the behavior of sessions is undefined when there are two session IDs.
I strongly recommend fixing the client. If that's not an option, you'll have to parse the headers manually.

Categories