Skip to main content

How does header() work?


A little context:

I needed to run PHP scripts in a browser, but I didn't want to go to all the trouble of installing a server and suffer the overhead of running a server on my computer and all the stuff that goes with it, including firewalls, blah blah blah.



So instead I wrote my own server. It's a simple PHP script that listens for connections on port 80 of my LAN IP, then I just load that IP in my browser and it works. It receives the HTTP request and starts a second PHP script using exec - this is so that I can make changes to it easily without having to restart the server script. This second PHP script parses the request, and finally include s the script that was actually being called. It gets the output from there, and sends the response back to the browser with appropriate headers (which I can change).



Yeah, it's a mess, but it works. It does what I need it to do.



Now for the question:

I can't use header() . It doesn't seem to be having any effect on what gets sent back to the browser through the socket connection. I have instead made a setheader() function, and store headers in an array to be prepended to the response.



I'd like to know how the header() function actually works internally, so that I might be able to use that function instead of my "hacked" one.


Source: Tips4allCCNA FINAL EXAM

Comments

  1. The header() function is totally ignored by the CLI SAPI. It has an effect on the Apache and CGI SAPIs though.

    Simply put, the CLI SAPI doesn't implement any logic in the sapi_*_header_* functions. Per example, for the CLI SAPI, in php_cli.c:

    static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */
    {
    /* We do nothing here, this function is needed to prevent that the fallback
    * header handling is called. */
    return SAPI_HEADER_SENT_SUCCESSFULLY;
    }
    /* }}} */


    All those functions basically return NULL, 0 or a fake success message.

    For the CGI SAPI, in cgi_main.c:

    static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
    {
    char buf[SAPI_CGI_MAX_HEADER_LENGTH];
    sapi_header_struct *h;
    zend_llist_position pos;
    zend_bool ignore_status = 0;
    int response_status = SG(sapi_headers).http_response_code;

    // Lots of other code...
    }




    You can easily make this work using the php-cgi binary and some array manipulation:

    server.php

    $script_to_run = 'script.php';
    exec('php-cgi '.escapeshellarg($script_to_run), $output);
    $separator = array_search("", $output);

    $headers = array_slice($output, 0, $separator);
    $body = implode("\r\n", array_slice($output, $separator+1));

    print_r($headers);
    print $body;


    script.php

    header('Content-Type: text/plain');
    echo 'Hello, World!';


    Output:

    Array
    (
    [0] => X-Powered-By: PHP/5.3.8
    [1] => Content-Type: text/plain
    )
    Hello, World!

    ReplyDelete
  2. The header() function works exactly as your implementation does: it just sends plain text headers in the response, before the page's content (that's why it will throw an error if any content has been already sent to the client). So, I think you're doing it the right way. Anyway, you have some problems in your implementation. I think installing a Web server would have been a lot easier.

    ReplyDelete
  3. And do you use correct CGI-style calling ? - otherwise most HTTP related functions will not work in PHP - and still CGI is not as best as library call from Apache or IIS

    Why just don't take EasyPHP or something like this ?

    PS What do you mean by "parsing request" ?

    ReplyDelete
  4. The actual sending headers is performed by the SAPI (server API) layer of PHP. Example SAPIs include mod_php for Apache and the CLI version of PHP which will be run when you call exec. In the case of the CLI SAPI, sending headers is a noop since it typically doesn't make sense to display HTTP headers for a script run over the command line.

    Try using php-cgi as the binary instead of PHP. The CGI SAPI should output the correct headers.

    ReplyDelete
  5. It's up to the SAPI module (the code that invokes the PHP script) to decide what to do with the headers. The CLI SAPI, which you're probably using, just ignores any headers set by the script. The CGI SAPI, which you could use with the php-cgi command, outputs them by default but supports a command line interface to suppress them. Ideally, you would just write your own SAPI module that interfaces properly with your web server.

    ReplyDelete
  6. A usual HTTP response looks like that:

    HTTP/1.1 200 OK
    Date: Thu, 10 Nov 2011 15:35:27 GMT
    Server: Apache
    Connection: close
    Transfer-Encoding: chunked
    Content-Type: text/html; charset=None

    <!DOCTYPE html>
    <html>
    ....


    The PHP function header() takes care of putting - well, - headers into the first part of the response. The actual HTML you can output using print and the likes.

    Now, if it's a PHP script, playing Apache, this script is responsible for putting your header lines in its response. header() only works if the output is sent to stdout and not custom written to a socket so that, after a PHP-CGI script ends, appropriate headers can be prepended to the output.

    ReplyDelete
  7. I know I'm gonna sound stupid, but why not just install wamp or lamp ? It's a really "unzip & run & voilà" type of solution, that would really spare your the trouble.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex