Weiterverarbeitung von PHP nach dem Senden der HTTP-Antwort

Lesezeit: 7 Minuten

Weiterverarbeitung von PHP nach dem Senden der HTTP Antwort
Benutzer1700214

Mein Skript wird vom Server aufgerufen. Vom Server erhalte ich ID_OF_MESSAGE und TEXT_OF_MESSAGE.

In meinem Skript werde ich eingehenden Text verarbeiten und eine Antwort mit Parametern generieren: ANSWER_TO_ID und RESPONSE_MESSAGE.

Das Problem ist, dass ich eine Antwort an eingehende sende "ID_OF_MESSAGE"aber der Server, der mir eine zu bearbeitende Nachricht sendet, setzt seine Nachricht als an mich zugestellt (das bedeutet, dass ich ihm eine Antwort an diese ID senden kann), nachdem er die HTTP-Antwort 200 erhalten hat.

Eine Lösung besteht darin, die Nachricht in der Datenbank zu speichern und einen Cron zu erstellen, der jede Minute ausgeführt wird, aber ich muss sofort eine Antwortnachricht generieren.

Gibt es eine Lösung, wie man die HTTP-Antwort 200 an den Server sendet und dann mit der Ausführung des PHP-Skripts fortfährt?

Vielen Dank

Weiterverarbeitung von PHP nach dem Senden der HTTP Antwort
vcampitelli

Jawohl. Du kannst das:

ignore_user_abort(true);//not required
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();
fastcgi_finish_request();//required for PHP-FPM (PHP > 5.3.3)

// now the request is sent to the browser, but the script is still running
// so, you can continue...

die(); //a must especially if set_time_limit=0 is used and the task ends

  • Ist es möglich, dies mit einer Keep-Alive-Verbindung zu tun?

    – Congelli501

    9. Juli 2014 um 19:14 Uhr

  • Exzellent!! Dies ist die einzige Antwort auf diese Frage, die wirklich funktioniert!!! 10p+

    – Martin_Seen

    1. August 2014 um 19:13 Uhr

  • Tolle Antwort! Das einzige, was ich geändert habe, war set_time_limit(0);. Sie möchten wahrscheinlich, dass es länger als die standardmäßigen 30 Sekunden läuft, aber auf unbestimmte Zeit könnte es zu Problemen kommen, wenn es in eine Endlosschleife geht! Ich habe einen längeren Wert in meinem eingestellt php.ini Datei.

    – CJ Dennis

    21. August 2014 um 14:25 Uhr

  • Bitte beachten Sie, dass wenn ein Content-Encoding-Header auf etwas anderes als „none“ gesetzt ist, dieses Beispiel unbrauchbar werden könnte, da es den Benutzer immer noch die volle Ausführungszeit (bis zum Timeout?) warten lassen würde. Um absolut sicher zu sein, dass es lokal und in der Produktionsumgebung funktioniert, setzen Sie den Header „content-encoding“ auf „none“: header("Content-Encoding: none")

    – Brian

    25. Juni 2015 um 7:04 Uhr


  • Tipp: Ich habe angefangen, PHP-FPM zu verwenden, also musste ich hinzufügen fastcgi_finish_request() Am Ende

    – vcampitelli

    16. September 2015 um 13:18 Uhr

1646842449 873 Weiterverarbeitung von PHP nach dem Senden der HTTP Antwort
Kosta Kontos

Ich habe hier viele Antworten gesehen, die die Verwendung vorschlagen ignore_user_abort(true); aber dieser Code ist nicht notwendig. All dies stellt sicher, dass Ihr Skript weiter ausgeführt wird, bevor eine Antwort gesendet wird, falls der Benutzer abbricht (indem er seinen Browser schließt oder die Escape-Taste drückt, um die Anfrage zu stoppen). Aber danach fragst du nicht. Sie bitten darum, die Ausführung fortzusetzen, NACHDEM eine Antwort gesendet wurde. Alles, was Sie brauchen, ist Folgendes:

// Buffer all upcoming output...
ob_start();

// Send your response.
echo "Here be response";

// Get the size of the output.
$size = ob_get_length();

// Disable compression (in case content length is compressed).
header("Content-Encoding: none");

// Set the content length of the response.
header("Content-Length: {$size}");

// Close the connection.
header("Connection: close");

// Flush all output.
ob_end_flush();
@ob_flush();
flush();

// Close current session (if it exists).
if(session_id()) session_write_close();

// Start your background work here.
...

Wenn Sie befürchten, dass Ihre Hintergrundarbeit länger dauert als das standardmäßige Zeitlimit für die Skriptausführung von PHP, dann bleiben Sie set_time_limit(0); oben.

  • Ich habe viele verschiedene Kombinationen ausprobiert, DAS ist diejenige, die funktioniert !!! Danke Kosta Kontos!!!

    – Martin_Seen

    5. August 2016 um 10:43 Uhr

  • Funktioniert perfekt auf Apache 2, PHP 7.0.32 und Ubuntu 16.04! Danke!

    – KyleBunga

    26. Januar 2019 um 0:03 Uhr

  • Ich habe andere Lösungen ausprobiert, und nur diese hat bei mir funktioniert. Die Reihenfolge der Zeilen ist ebenfalls wichtig.

    – Siniša

    1. Oktober 2019 um 15:27 Uhr

  • Ich kann beim besten Willen nicht verstehen, warum ob_flush() ist hier erforderlich, da es eine Benachrichtigung auslöst PHP Notice: ob_flush(): failed to flush buffer. No buffer to flush in php shell code on line 1. Ohne geht das komischerweise nicht. Ich schätze, es tut doch etwas…

    – Von einem Grue gefressen

    23. Juli 2021 um 11:20 Uhr

  • @billynoah Ich denke, es wird nicht benötigt. ob_end_flush() macht das gleiche wie ob_flush außer dass es den Puffer schließt (daher Aufruf ob_flush() nach dem ob_end_flush() erzeugt die Warnung, auf die Sie gestoßen sind.

    – Sebi2020

    3. September 2021 um 18:25 Uhr


1646842450 832 Weiterverarbeitung von PHP nach dem Senden der HTTP Antwort
DarkNeuron

Wenn Sie FastCGI-Verarbeitung oder PHP-FPM verwenden, können Sie:

session_write_close(); //close the session
ignore_user_abort(true); //Prevent echo, print, and flush from killing the script
fastcgi_finish_request(); //this returns 200 to the user, and processing continues

// do desired processing ...
$expensiveCalulation = 1+1;
error_log($expensiveCalculation);

Quelle: https://www.php.net/manual/en/function.fastcgi-finish-request.php

PHP-Problem Nr. 68722: https://bugs.php.net/bug.php?id=68772

  • Danke dafür, nachdem ich ein paar Stunden damit verbracht hatte, funktionierte dies für mich in nginx

    – Ehsan

    14. Februar 2017 um 8:33 Uhr

  • Danke DarkNeuron! Tolle Antwort für uns mit php-fpm, gerade mein Problem gelöst!

    – Siniša

    1. Januar 2020 um 6:54 Uhr

  • Brillant! Ich habe gerade Stunden damit verbracht, herauszufinden, warum unsere App auf einer Seite, auf der wir die Ausgabepufferung verwendet haben, nicht mehr funktioniert, nachdem wir sie auf einen neuen Server verschoben haben, und das war der Schlüssel. Danke!

    – D Durham

    12. Dezember 2020 um 16:04 Uhr

  • Einfach und effizient, der Code, den wir mögen. Danke

    – PaulCrp

    20. Februar um 18:44 Uhr

Ich habe ein paar Stunden mit diesem Problem verbracht und bin mit dieser Funktion gekommen, die auf Apache und Nginx funktioniert:

/**
 * respondOK.
 */
protected function respondOK()
{
    // check if fastcgi_finish_request is callable
    if (is_callable('fastcgi_finish_request')) {
        /*
         * This works in Nginx but the next approach not
         */
        session_write_close();
        fastcgi_finish_request();

        return;
    }

    ignore_user_abort(true);

    ob_start();
    $serverProtocole = filter_input(INPUT_SERVER, 'SERVER_PROTOCOL', FILTER_SANITIZE_STRING);
    header($serverProtocole.' 200 OK');
    header('Content-Encoding: none');
    header('Content-Length: '.ob_get_length());
    header('Connection: close');

    ob_end_flush();
    ob_flush();
    flush();
}

Sie können diese Funktion vor Ihrer langen Verarbeitung aufrufen.

Die Antwort von @vcampitelli wurde etwas geändert. Denke nicht, dass du das brauchst close Header. Ich habe in Chrome doppelte geschlossene Header gesehen.

<?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);

  • Ich habe dies in der ursprünglichen Antwort erwähnt, aber ich werde es auch hier sagen. Sie müssen die Verbindung nicht unbedingt schließen, aber dann wird das nächste Asset, das auf derselben Verbindung angefordert wird, warten müssen. Sie könnten also den HTML-Code schnell bereitstellen, aber dann könnte eine Ihrer JS- oder CSS-Dateien langsam geladen werden, da die Verbindung die Antwort von PHP erhalten muss, bevor sie das nächste Asset erhalten kann. Aus diesem Grund ist es eine gute Idee, die Verbindung zu schließen, damit der Browser nicht auf die Freigabe warten muss.

    – Nate Lampton

    17. September 2015 um 3:42 Uhr

Ich verwende dafür die PHP-Funktion register_shutdown_function.

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

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

Bearbeiten: Das obige funktioniert nicht. Anscheinend wurde ich von einer alten Dokumentation in die Irre geführt. Das Verhalten von register_shutdown_function hat sich seit PHP 4.1 geändert Verknüpfung Verknüpfung

  • Ich habe dies in der ursprünglichen Antwort erwähnt, aber ich werde es auch hier sagen. Sie müssen die Verbindung nicht unbedingt schließen, aber dann wird das nächste Asset, das auf derselben Verbindung angefordert wird, warten müssen. Sie könnten also den HTML-Code schnell bereitstellen, aber dann könnte eine Ihrer JS- oder CSS-Dateien langsam geladen werden, da die Verbindung die Antwort von PHP erhalten muss, bevor sie das nächste Asset erhalten kann. Aus diesem Grund ist es eine gute Idee, die Verbindung zu schließen, damit der Browser nicht auf die Freigabe warten muss.

    – Nate Lampton

    17. September 2015 um 3:42 Uhr

Weiterverarbeitung von PHP nach dem Senden der HTTP Antwort
Matthäus Slyman

Diese Frage habe ich Rasmus Lerdorf im April 2012 gestellt und diese Artikel zitiert:

Ich habe die Entwicklung einer neuen in PHP integrierten Funktion vorgeschlagen, um die Plattform zu benachrichtigen, dass keine weitere Ausgabe (auf stdout?) Generiert wird (eine solche Funktion könnte sich um das Schließen der Verbindung kümmern). Rasmus Lerdorf antwortete:

Sehen Getriebemann. Sie möchten wirklich nicht, dass Ihre Frontend-Webserver eine solche Backend-Verarbeitung durchführen.

Ich kann seinen Standpunkt verstehen und seine Meinung für einige Anwendungen / Ladeszenarien unterstützen! Unter einigen anderen Szenarien sind die Lösungen von vcampitelli et al. jedoch gut.

983290cookie-checkWeiterverarbeitung von PHP nach dem Senden der HTTP-Antwort

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy