How to isolate the HTTP headers/body from a PHP Sockets request
You can separate the header from the the body by splitting up on a double linebreak. It should be <CRLF><CRLF>
so this would normally work:
list($header, $body) = explode("\r\n\r\n", $response, 2);
More reliably you should use a regex to catch linebreak variations (super unlikely to ever happen):
list($header, $body) = preg_split("/\R\R/", $response, 2);
The thing with the 4d
and 0
is called the chunked encoding. (It's hex-numbers separated with another linebreak, and inidicate the length of the following raw content block).
To clear that up you have to look at the headers first, and see if there is an according Transfer-Encoding:
entry. This is were it gets complicated, and advisable to use one of the myriad of existing HTTP userland processing classes. PEAR has one.
Related videos on Youtube
Rob
Updated on June 04, 2022Comments
-
Rob almost 2 years
I'm using a socket connection in PHP to post data to an Apache webserver. I'm a bit new to this technique, and I am not sure how to isolate the headers from the body of the response.
Sending Code:
<?php // collect data to post $postdata = array( 'hello' => 'world' ); $postdata = http_build_query($postdata); // open socket, send request $fp = fsockopen('127.0.0.1', 80); fwrite($fp, "POST /server.php HTTP/1.1\r\n"); fwrite($fp, "Host: fm1\r\n"); fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n"); fwrite($fp, "Content-Length: ".strlen($postdata)."\r\n"); fwrite($fp, "Connection: close\r\n"); fwrite($fp, "\r\n"); fwrite($fp, $postdata); // go through result $result = ""; while(!feof($fp)){ $result .= fgets($fp); } // close fclose($fp); // display result echo $result; ?>
Server Code:
Hello this is server. You posted: <pre> <?php print_r($_POST); ?> </pre>
When posting to one server, I get:
HTTP/1.1 200 OK Date: Fri, 06 Jan 2012 09:55:27 GMT Server: Apache/2.2.15 (Win32) mod_ssl/2.2.15 OpenSSL/0.9.8m PHP/5.3.2 X-Powered-By: PHP/5.3.2 Content-Length: 79 Connection: close Content-Type: text/html Hello this is server. You posted: <pre> Array ( [hello] => world ) </pre>
As expected. I want to strip off the headers though, and just read the body from "Hello this is server....." onwards. How can i reliably detect the end of the headers and read the body into a variable?
Also, another server I've tested on replies with this:
HTTP/1.1 200 OK Date: Fri, 06 Jan 2012 10:02:04 GMT Server: Apache/2 X-Powered-By: PHP/5.2.17 Connection: close Transfer-Encoding: chunked Content-Type: text/html 4d Hello this is server. You posted: <pre> Array ( [hello] => world ) </pre> 0
What are the "4d" and "0" around the body text??
Thanks!
PS before someone says use CURL, I can't unfortunately :-(
-
Oberst about 8 yearsFWIW: His answer would still work for you. The key is the "2" in the third param of
explode
. Means There will only ever be a max of 2 items in an array created withexplode
. So inlist($header, $body)
, the first "chunk" of the array would be assigned to$headers
, and everything else, regardless of how many\r\n
s exist, would be assigned to$body
.