continue processing php after sending http response

后端 未结 12 796
旧时难觅i
旧时难觅i 2020-11-22 13:06

My script is called by server. From server I\'ll receive ID_OF_MESSAGE and TEXT_OF_MESSAGE.

In my script I\'ll handle incoming text and ge

相关标签:
12条回答
  • 2020-11-22 13:27

    I asked this question to Rasmus Lerdorf in April 2012, citing these articles:

    • https://www.zulius.com/how-to/close-browser-connection-continue-execution/
    • close a connection early
    • http://php.net/manual/en/features.connection-handling.php

    I suggested the development of a new PHP built-in function to notify the platform that no further output (on stdout?) will be generated (such a function might take care of closing the connection). Rasmus Lerdorf responded:

    See Gearman. You really really don't want your frontend Web servers doing backend processing like this.

    I can see his point, and support his opinion for some applications/ loading scenarios! However, under some other scenarios, the solutions from vcampitelli et al, are good ones.

    0 讨论(0)
  • 2020-11-22 13:28

    I use the php function register_shutdown_function for this.

    void register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] )
    

    http://php.net/manual/en/function.register-shutdown-function.php

    Edit: The above is not working. It seems I was misled by some old documentation. The behaviour of register_shutdown_function has changed since PHP 4.1 link link

    0 讨论(0)
  • 2020-11-22 13:28

    in case of php file_get_contents use, connection close is not enough. php still wait for eof witch send by server.

    my solution is to read 'Content-Length:'

    here is sample :

    response.php:

     <?php
    
    ignore_user_abort(true);
    set_time_limit(500);
    
    ob_start();
    echo 'ok'."\n";
    header('Connection: close');
    header('Content-Length: '.ob_get_length());
    ob_end_flush();
    ob_flush();
    flush();
    sleep(30);
    

    Note the "\n" in response to close line, if not the fget read while wait eof.

    read.php :

    <?php
    $vars = array(
        'hello' => 'world'
    );
    $content = http_build_query($vars);
    
    fwrite($fp, "POST /response.php HTTP/1.1\r\n");
    fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
    fwrite($fp, "Content-Length: " . strlen($content) . "\r\n");
    fwrite($fp, "Connection: close\r\n");
    fwrite($fp, "\r\n");
    
    fwrite($fp, $content);
    
    $iSize = null;
    $bHeaderEnd = false;
    $sResponse = '';
    do {
        $sTmp = fgets($fp, 1024);
        $iPos = strpos($sTmp, 'Content-Length: ');
        if ($iPos !== false) {
            $iSize = (int) substr($sTmp, strlen('Content-Length: '));
        }
        if ($bHeaderEnd) {
            $sResponse.= $sTmp;
        }
        if (strlen(trim($sTmp)) == 0) {
            $bHeaderEnd = true;
        }
    } while (!feof($fp) && (is_null($iSize) || !is_null($iSize) && strlen($sResponse) < $iSize));
    $result = trim($sResponse);
    

    As you can see this script dosent wait about eof if content length is reach.

    hope it will help

    0 讨论(0)
  • 2020-11-22 13:30

    I can't install pthread and neither the previous solutions work for me. I found only the following solution to work (ref: https://stackoverflow.com/a/14469376/1315873):

    <?php
    ob_end_clean();
    header("Connection: close");
    ignore_user_abort(); // optional
    ob_start();
    echo ('Text the user will see');
    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush(); // Strange behaviour, will not work
    flush();            // Unless both are called !
    session_write_close(); // Added a line suggested in the comment
    // Do processing here 
    sleep(30);
    echo('Text user will never see');
    ?>
    
    0 讨论(0)
  • 2020-11-22 13:34

    Modified the answer by @vcampitelli a bit. Don't think you need the close header. I was seeing duplicate close headers in Chrome.

    <?php
    
    ignore_user_abort(true);
    
    ob_start();
    echo '{}';
    header($_SERVER["SERVER_PROTOCOL"] . " 202 Accepted");
    header("Status: 202 Accepted");
    header("Content-Type: application/json");
    header('Content-Length: '.ob_get_length());
    ob_end_flush();
    ob_flush();
    flush();
    
    sleep(10);
    
    0 讨论(0)
  • 2020-11-22 13:38

    Yes. You can do this:

    ignore_user_abort(true);
    set_time_limit(0);
    
    ob_start();
    // do initial processing here
    echo $response; // send the response
    header('Connection: close');
    header('Content-Length: '.ob_get_length());
    ob_end_flush();
    ob_flush();
    flush();
    
    // now the request is sent to the browser, but the script is still running
    // so, you can continue...
    
    0 讨论(0)
提交回复
热议问题