Recently I’ve come across APIs and mainly event management systems that need to receive a HTTP 200 OK response upon sending a request to our server. For example, if you need to integrate Slack Events API your server has to respond a HTTP 200 OK
within 3 seconds to every event it receives. Another example is where your server has to respond an [accepted]
response within 10 seconds to Adyen notifications.
Keep the execution after sending HTTP response
In order to handle these situations it’s recommended to keep replying to notifications separated from processing them. Another solution is to first return a successful response and then continue execution of the script in the same process. To achieve this I’ve written the following function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/** * Respond 200 OK with an optional * This is used to return an acknowledgement response indicating that the request has been accepted and then the script can continue processing * * @param null $text */ public function respondOK($text = null) { // check if fastcgi_finish_request is callable if (is_callable('fastcgi_finish_request')) { if ($text !== null) { echo $text; } /* * http://stackoverflow.com/a/38918192 * This works in Nginx but the next approach not */ session_write_close(); fastcgi_finish_request(); return; } ignore_user_abort(true); ob_start(); if ($text !== null) { echo $text; } $serverProtocol = filter_input(INPUT_SERVER, 'SERVER_PROTOCOL', FILTER_SANITIZE_STRING); header($serverProtocol . ' 200 OK'); // Disable compression (in case content length is compressed). header('Content-Encoding: none'); header('Content-Length: ' . ob_get_length()); // Close the connection. header('Connection: close'); ob_end_flush(); ob_flush(); flush(); } |
So assuming you’ve got a function named handleEvent()
which is called whenever your server receives a request you can use respondOK()
function as follow:
1 2 3 4 5 6 |
public function handleEvent() { $this->respondOK(); // your very long process goes here ... } |
17 November 2017 at 3:38 am
Any idea why it gets stuck when trying to fetch an API after sending resposneOK()?
Try something like
`
<?php
$firstHit = file_get_contents($entrypoint);
error_log('before response: ' . $firstHit);
resposneOK();
sleep(1);
error_log('slept for 1 sec');
$secondHit = file_get_contents($entrypoint);
error_log('Second hit: ' . $secondHit);
die;
5 March 2018 at 6:47 pm
Hi thanks for your post. I’ve got a situation where I need to send multiple emails to a rabbitmq queue looping through the emails from database using foreach this is causing a long waiting time for the user to wait for response. Do you think I can use this function?
22 May 2018 at 7:32 am
Hi there. Great snippet. Thanks.
Any reason why I can get it to work on MAMP?
I had to use it on a VPS running Ubuntu and Apache/PHP to get it to work.
22 May 2018 at 7:52 am
Instead of using the following technique …
Wouldn’t it be more portal to use the http_response_code() PHP function?
4 July 2018 at 12:40 am
I implemented your solution on PHP running on Windows Server 2012 R2 (IIS 6.2).
Sadly it does not work. I call $this->respondOK(); early on the handleEvent function (1 sec after it start) , but the calling system (that is the “Slack” in my architecture) is still waiting until my script is finished (60 seconds later).
Any ideas?