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.
Related
As I'm trying to configure my server, I made a var_dump of $_SERVER and noticed an (to me and a quick Google) unknown variable: what is the $_SERVER variable $_SERVER["HTTP_TE"]?
See the manual:
All HTTP headers sent to the script are made available through the $SERVER array, with names prefixed by 'HTTP'.
HTTP_TE will be a TE header sent by the client.
The TE request header specifies the transfer encodings the user agent is willing to accept. (you could informally call it Accept-Transfer-Encoding, which would be more intuitive).
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
When I do a GET request for a url on my laravel web app, I do the following in my controller to retrieve a custom header:
Request::header('customheader');
This value is always blank, though the header is clearly visible in Chrome Developer Tools in the Request Headers
While troubleshooting I tried using a standard header: Connection
Looking at the request headers, I expected the following:
Request::header('Connection') == "keep-alive"
What is super weird is that this instead returned "close" aka, the value of Connection in the Response Headers. This explains why my custom header is showing up empty (it is not in the response, but the request).
So what gives? The Laravel docs clearly state that this is the way to retreive REQUEST headers.
http://laravel.com/docs/4.2/requests#request-information
Any soltuions to get what I want?
edit: $_SERVER["HTTP_HEADER_NAME"] as proposed in https://stackoverflow.com/a/541450/1800023 gives me the same results. The values are those from the RESPONSE headers.
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.
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.