How to isolate the HTTP headers/body from a PHP Sockets request

10,007

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.

Share:
10,007

Related videos on Youtube

Rob
Author by

Rob

Updated on June 04, 2022

Comments

  • Rob
    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
    Oberst about 8 years
    FWIW: 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 with explode. So in list($header, $body), the first "chunk" of the array would be assigned to $headers, and everything else, regardless of how many \r\ns exist, would be assigned to $body.