use*_*214 91 php http response
我的脚本由服务器调用.从服务器我会收到ID_OF_MESSAGE
和TEXT_OF_MESSAGE
.
在我的脚本中,我将处理传入的文本并使用params生成响应:ANSWER_TO_ID
和RESPONSE_MESSAGE
.
问题是我正在向incomming发送响应"ID_OF_MESSAGE"
,但是在收到http响应200之后,向我发送消息的服务器将把他的消息设置为发送给我(这意味着我可以发送给他的响应).
解决方案之一是将消息保存到数据库并制作一些将每分钟运行的cron,但我需要立即生成响应消息.
是否有一些解决方案如何发送到服务器http响应200而不是继续执行PHP脚本?
非常感谢
vca*_*lli 179
是.你可以这样做:
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...
Run Code Online (Sandbox Code Playgroud)
Kos*_*tos 39
我在这里看到很多回复建议使用,ignore_user_abort(true);
但这段代码不是必需的.所有这一切都是为了确保您的脚本在用户中止(通过关闭浏览器或按下escape以停止请求)发送响应之前继续执行.但这不是你要问的.您要求在发送响应后继续执行.您所需要的只是以下内容:
// 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.
...
Run Code Online (Sandbox Code Playgroud)
如果您担心您的后台工作将花费比PHP的默认脚本执行时间限制更长的时间,那么请坚持 set_time_limit(0);
到顶部.
Dar*_*ron 25
如果您正在使用FastCGI处理或PHP-FPM,您可以:
session_write_close(); //close the session
fastcgi_finish_request(); //this returns 200 to the user, and processing continues
// do desired processing ...
$expensiveCalulation = 1+1;
error_log($expensiveCalculation);
Run Code Online (Sandbox Code Playgroud)
资料来源:http://fi2.php.net/manual/en/function.fastcgi-finish-request.php
Ehs*_*san 17
我在这个问题上花了几个小时,我已经使用了这个适用于Apache和Nginx的函数:
/**
* 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();
}
Run Code Online (Sandbox Code Playgroud)
您可以在长时间处理之前调用此函数.
稍微修改了@vcampitelli 的答案。不要认为您需要close
标题。我在 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);
Run Code Online (Sandbox Code Playgroud)
我在 2012 年 4 月向 Rasmus Lerdorf 提出了这个问题,并引用了以下文章:
我建议开发一个新的 PHP 内置函数来通知平台不会生成进一步的输出(在标准输出上?)(这样的函数可能会负责关闭连接)。拉斯穆斯·勒多夫回应:
参见吉尔曼。您确实不希望前端 Web 服务器进行这样的后端处理。
我可以理解他的观点,并支持他对某些应用程序/加载场景的看法!然而,在其他一些场景下,vcampitelli 等人的解决方案是不错的。
我无法安装 pthread,之前的解决方案都不适合我。我发现只有以下解决方案有效(参考: 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');
?>
Run Code Online (Sandbox Code Playgroud)