php : Show the headers received from the browser
So when a browser makes a HTTP request to a server, it is in the form some headers (get/post, cookies, host, User Agent, etc..). Is there a way I can read and display them in a php script? And yes $_GET, $_POST and $_COOKIE are there alright. I was looking for the rest of header info. eg http://pgl.yoyo.org/http/browser-headers.php Thanks.
4 Answers 4
get_headers() function is what you are looking for. As quoted
get_headers — Fetches all the headers sent by the server in response to a HTTP request
$url = 'http://www.example.com'; print_r(get_headers($url));
Outputs all the information the send by the server:
[0] => HTTP/1.1 200 OK [1] => Date: Sat, 29 May 2004 12:28:13 GMT [2] => Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) [3] => Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT [4] => ETag: "3f80f-1b6-3e1cb03b" [5] => Accept-Ranges: bytes [6] => Content-Length: 438 [7] => Connection: close [8] => Content-Type: text/html )
Update
TO receive the information that is send by browsers, they can be accessed from $_SERVER super global variable. For example, the following snippet gives all the browser related information.
echo $_SERVER['HTTP_USER_AGENT'];
- REQUEST_METHOD : gives the HTTP Request method such as GET, HEAD, Put, Post
- HTTP_HOST : gives the HOST information
- HTTP_COOKIE : gives the raw information about the Cookie header [Source]
Is it possible to log all HTTP request headers with Apache?
How to make a record into the logfile the contents of the HTTP request header (all) as received by apache? Currently my apache combined log format configuration is:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%i\" \"%i\" \"%i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b \"%i\" \"%i\" \"%i\" \"%i\" \"%i\" \"%i\"" combined
4 Answers 4
mod_log_forensic is what you want, but it may not be included/available with your Apache install by default.
LoadModule log_forensic_module /usr/lib64/httpd/modules/mod_log_forensic.so ForensicLog $/forensic.log
Note: Your path may vary, such as /usr/lib/apache2/modules/mod_log_forensic.so
Thanks, this is the correct answer. Here’s how to set that up in httpd.conf. (Ugh, no linefeeds in comments??) LoadModule log_forensic_module /usr/lib64/httpd/modules/mod_log_forensic.so
Note, if you use a2enmod log_forensic to enable the module you don’t need to use the LoadModule line.
I like to use LoadModule rather than a2enmod, because it can be activated only for an specific virtualhost, then I can just comment the line and reload apache, everything is back to normal!
In recent versions of apache or depending on your system, the path to the mod could be /usr/lib/apache2/modules/mod_log_forensic.so and the typical folder to save the log would be $
As you did write correctly, the code for logging a specific header is %i where foobar is the name of the header. So, the only solution is to create a specific format string. When you expect a non-standard header like x-my-nonstandard-header, then use %i . If your server is going to ignore this non-standard-header, why should you want to write it to your logfile? An unknown header has absolutely no effect to your system.
It’s still useful enough to be able to log all HTTP headers passed onto the apache machine. I would rather have a more flexible system than have to edit the LogFormat everytime a new header is introduced.
As noted in the linked article, a server may include non-standard, custom, application specific headers. This solution will not catch those if the person configuring Apache is unaware of them. As for an «unknown header having no effect on your system,» you have no idea whether that’s the case or not. Any number of web frameworks might leverage headers you didn’t expect it to.
@Ehtesh I second that, being behind a load-balancer that modifies the headers. I’d love to see exactly what I’m getting, something like % with names.
If you’re interested in seeing which specific headers a remote client is sending to your server, and you can cause the request to run a CGI script, then the simplest solution is to have your server script dump the environment variables into a file somewhere.
e.g. run the shell command «env > /tmp/headers» from within your script
Then, look for the environment variables that start with HTTP_.
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 HTTP_ACCEPT_ENCODING=gzip, deflate HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.5 HTTP_CACHE_CONTROL=max-age=0
Each of those represents a request header.
Note that the header names are modified from the actual request. For example, «Accept-Language» becomes «HTTP_ACCEPT_LANGUAGE», and so on.
How to capture full HTTP request data (headers and body) with PHP?
I have a problem implementing an API that works with Java, but fails to work with cURL. We’ve gone through everything so far and there must be something that is different between the requests that Java makes and what we make. In PHP we can get header data by looking at $_SERVER[‘HTTP_*’] variables and we can get request body from file_get_contents(‘php://input’); But we cannot get the exact data sent from user agent to client. Is it possible to get the full request, that user agent sends, with PHP? Headers and body included? If so, then how? The only example I found is here, but this one gets the body the way I mentioned, while it gets headers by parsing through $_SERVER , which seems like a hack since it’s never 100% of what was actually sent. All help and tips are appreciated!
3 Answers 3
for headers you can try apache_request_headers() and for body I dont know other method than file_get_contents(‘php://input’);
These are fine, but we were looking for more of a byte-level comparison. Anyways, this is the best we have I suppose.
since headers comes from apache server in php you can’t do a thing maybe apache have something.. maybe in logs then read with php but that’s hack for hack 😀
Old question, but for anyone needing to do this in the future. The best (probably only) way would be to take full control of the server by being the server.
Set up a socket server listening on port 80 (if this is all you need the server to do), or any other port if 80 is not available.
That way you can capture the request completely unmodified. Examples of basic socket servers are plentiful, here is a simplified version of the latest one I implemented, which will print the full request:
//Create socket while (($sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) < dlog("socket_create() failed: reason: " . socket_strerror(socket_last_error())); sleep(1); >//Reduce blocking if previous connections weren't ended correctly if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) < dlog("socket_set_option() failed: reason: " . socket_strerror(socket_last_error($sock))); exit; >//Bind to port $tries = 0; while (@socket_bind($sock, 0, $port) === false) < dlog("socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock))); sleep(1); $tries++; if ($tries>30) < dlog("socket_bind() failed 30 times giving up. "); exit; >> //Start listening while (@socket_listen($sock, 5) === false) < dlog("socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock))); sleep(1); >//Makes it possible to accept several simultaneous connections socket_set_nonblock($sock); //Keeps track of active connections $clients = array(); dlog("server started. "); while(true) < //Accept new connections while (($msgsock = @socket_accept($sock)) !== false) < //Prevent blocking socket_set_nonblock($msgsock); //Get IP - just for logging socket_getpeername($msgsock, $remote_address); //Add new client to array $clients[] = array('sock' =>$msgsock, 'timeout' => time()+30, 'ip' => $remote_address); dlog("$remote_address connected, client count: ".count($clients)); > //Loop existing clients and read input foreach($clients as $key => $client) < $rec = ''; $buf = ''; while (true) < //Read 2 kb into buffer $buf = socket_read($clients[$key]['sock'], 2048, PHP_BINARY_READ); //Break if error reading if ($buf === false) break; //Append buffer to input $rec .= $buf; //If no more data is available socket read returns an empty string - break if ($buf === '') break; >if ($rec=='') < //If nothing was received from this client for 30 seconds then end the connection if ($clients[$key]['timeout']
To start the server on port 8080 just run php filename.php 8080 from a shell.