128 votes

continuer à traiter php après avoir envoyé la réponse http

Mon script est appelé par le serveur. Du serveur, je recevrai ID_OF_MESSAGE y TEXT_OF_MESSAGE .

Dans mon script, je vais gérer le texte entrant et générer la réponse avec les paramètres : ANSWER_TO_ID y RESPONSE_MESSAGE .

Le problème est que j'envoie une réponse à une demande incommensurable. "ID_OF_MESSAGE" Mais le serveur qui m'a envoyé un message à gérer va considérer que son message m'a été remis (ce qui signifie que je peux lui envoyer une réponse à cet ID), après avoir reçu la réponse http 200.

L'une des solutions consiste à enregistrer le message dans la base de données et à créer un cron qui s'exécutera toutes les minutes, mais j'ai besoin de générer un message de réponse immédiatement.

Existe-t-il une solution pour envoyer au serveur une réponse http 200 et continuer à exécuter le script php script ?

Merci beaucoup.

1voto

Jonathan Points 1011

Il existe une autre approche, qui vaut la peine d'être envisagée si vous ne souhaitez pas modifier les en-têtes de réponse. Si vous démarrez un thread sur un autre processus, la fonction appelée n'attendra pas sa réponse et retournera au navigateur avec un code http finalisé. Vous devrez configurer pthread .

class continue_processing_thread extends Thread 
{
     public function __construct($param1) 
     {
         $this->param1 = $param1
     }

     public function run() 
     {
        //Do your long running process here
     }
}

//This is your function called via an HTTP GET/POST etc
function rest_endpoint()
{
  //do whatever stuff needed by the response.

  //Create and start your thread. 
  //rest_endpoint wont wait for this to complete.
  $continue_processing = new continue_processing_thread($some_value);
  $continue_processing->start();

  echo json_encode($response)
}

Une fois que nous aurons exécuté $continue_processing->start() PHP n'attendra pas le résultat du retour de ce fil et donc, en ce qui concerne le rest_endpoint. C'est fait.

Quelques liens pour vous aider avec les pthreads

Bonne chance.

0voto

Wakeel Points 128

En plus des réponses, j'ai renvoyé une chaîne JSON comme réponse. J'ai découvert que la réponse est tronquée pour une raison inconnue. La solution au problème était d'ajouter un espace supplémentaire :

echo $json_response;
//the fix
echo str_repeat(' ', 10);

0voto

Charliexyx Points 89

J'ai un ajout important à toutes les autres grandes réponses !
TL;DR :
ajouter

echo str_repeat(' ', 1024);

Dans mon cas d'utilisation, je voudrais marquer l'appel d'API comme "Accepté" et ne pas faire attendre le client pour la fin du traitement.

En fait, ça semble correct : Le client devrait cesser d'attendre la réponse lorsqu'il reçoit l'en-tête "Connection : close", mais en fait, au moins MY php n'envoie pas encore ces en-têtes. (testé avec deux serveurs PHP différents, et chacun via un navigateur et un client Insomnia).

Il y a un comportement spécial qui fait que flush() n'enverra pas le premier contenu si au moins une quantité spéciale d'octets n'a pas encore été envoyée (dans mon cas 1024 octets). (Il s'agit probablement d'un correctif au cas où il y aurait des espaces blancs en tête ou en queue dans les fichiers php qui sont en fait traités comme une déclaration d'écho ou quelque chose de ce genre qui empêcherait les déclarations header() ultérieures de prendre effet).

Pour résoudre ce problème, on peut envoyer 1024 caractères d'espacement de tête qui seront ignorés par les interprètes JSON/XML/HTML.

Le code complet ressemble donc à ceci :

ob_start();
echo str_repeat(' ', 1024);
echo $response; // send the response
header('Connection: close');
header('Content-Length: '.ob_get_length());
ob_end_flush();
@ob_flush();
flush();

(Voici quelques arguments à l'appui, je n'arrive pas à trouver la bonne source en ce moment : Comment purger la sortie après chaque appel `echo` ? )

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X