I have two files client.php and server.php.
The client file send a HTTP request to the server file. The server file can be very slow to process the request so I just want it to answer to the client “OK the request is correct, the result will be sent by email”.
But I don’t know to make the server close the HTTP request with suitable headers and continue its job. If I specify a timeout of 1 second, I wont’t be able to know if the request will be accepted by the server.
So is it possible in PHP ? Do you know how ?
client.php:
<?php
$resource = curl_init();
curl_setopt($resource, CURLOPT_URL, 'http://localhost/server.php');
curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
curl_setopt($resource, CURLOPT_TIMEOUT, 30);
curl_exec($resource);
server.php
<?php
header('200 OK');
echo 'OK the request is correct, the result will be sent by email';
// How to write the method below?
send_result_to_client();
// Simulates a slow process
sleep(60);
Ok I found the solution.
In the function send_result_to_client should seem to :
function send_result_to_client()
{
$myString = '...';
$size = strlen($myString);
header("Content-Length: $size");
header('Connection: close');
flush();
}
I’m sorry, but sending
Connection:closeandflush()is not the solution – not portably across servers or browsers. It may seem to be a solution because it appears to work when you run a simple test. If you try it withand then do nothing, or worse, do what any user will do – close the window as soon as he sees the “You’ll be notified by email” – you’ll discover that on most platforms, the email never gets sent, and the job never gets done.
curlmay terminate ifConnection:closeandContent-Lengthbytes have been received, but from RFC 2616,But the server is not closing the connection, not really. That would require a
die()orexit()before the job has been processed.So your script continues executing only until the browser actually closes the connection – at that point (usually) the processing aborts. Maybe on some platforms it doesn’t, but don’t count on it.
You may try to ameliorate the situation with another hack:
but it is, indeed, a hack.
There are no truly portable solutions. Usually, as suggested by Manatok, the job is queued somewhere else, and the queue processed asynchronously by another thread. This is possibly the best solution.
Other possibilities involve a different and maybe simpler way to do the same thing, using atd and at command (or equivalent under Windows) to queue the job. You can create the “job control” with
shell_execby piping a new PHP script to be executed byatd:(or more efficiently, running “
at now” withpopenand writing the command to execute to itsstdin).See for example:
https://github.com/treffynnon/PHP-at-Job-Queue-Wrapper
You can also try to spawn a concurrent job, through
popenorshell_exec, but you need to detach it from the server process, or you’ll find the system hogged by copies of the job executable (orCMD.EXEif you do this under Windows).See:
Asynchronous shell exec in PHP