我正在尝试使用Slack Custom命令而不太确定如何使用延迟消息,因为Yoda Speak外部API需要3秒以上的时间才能响应。
我做了以下事情:
/Yoda
并收到reponse_url
。post
以下内容用于回复网址。$data_string = '{"response_type": "in_channel", "text":"Checking,please wait..."}' ; $chs = curl_init(); curl_setopt($chs, CURLOPT_URL, $response_url); curl_setopt($chs, CURLOPT_POST, true); curl_setopt($chs, CURLOPT_POSTFIELDS, $data_string); curl_setopt($chs, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($chs, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($chs, CURLOPT_RETURNTRANSFER, true); curl_setopt($chs, CURLOPT_POST, 1); curl_setopt($chs, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); $results = curl_exec($chs);
$chsres = curl_init(); curl_setopt($chsres, CURLOPT_URL, "https://yoda.p.mashape.com/yoda?sentence=welcome+to+stack"); curl_setopt($chsres, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($chsres, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($chsres, CURLOPT_VERBOSE, true); curl_setopt($chsres, CURLOPT_TIMEOUT, 45); curl_setopt($chsres, CURLOPT_RETURNTRANSFER, true); curl_setopt($chsres, CURLOPT_HTTPHEADER, array('Content-Type:application/json', "X-Mashape-Key:> deMeGoBfMvmshQSemozTqJEY9z0jp1eIhuAjsnx9cQAQsHUifD")); $resultchsres = curl_exec($chsres); echo $resultchsres;
有人可以让我知道如何使用延迟回复摆脱超时错误吗?
更新后的代码:
$response_url = $_POST['response_url'];
$text = $_POST['text'];
$term = str_replace(' ', '+', $text);
//https://paypal.slack.com/services/B0VQMHX8W#service_setup
//initial respond with 200OK for timeout
ignore_user_abort(true);
set_time_limit(0);
ob_start();
echo('{"response_type": "in_channel", "text": "Checking, please wait..."}');
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("Content-Type: application/json");
header('Content-Length: '.ob_get_length());
ob_end_flush();
ob_flush();
flush();
$chsres = curl_init();
curl_setopt_array($chsres, array(
CURLOPT_URL => "https://yoda.p.mashape.com/yoda?sentence=$term",
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_SSL_VERIFYHOST => FALSE,
CURLOPT_VERBOSE => true,
CURLOPT_RETURNTRANSFER => FALSE,
CURLOPT_HTTPHEADER => array('Content-Type:application/json', "X-Mashape-Key: deMeGoBfMvmshQSemozTqJEY9z0jp1eIhuAjsnx9cQAQsHUifD"),
CURLOPT_RETURNTRANSFER => true
));
$yodaresponse = curl_exec($chsres);
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $response_url,
CURLOPT_POST => 1,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $yodaresponse
));
$resp = curl_exec($curl);
var_dump($resp);
curl_close($curl);
我仍然得到相同的错误" Darn - 斜杠命令没有工作(错误消息:Timeout was reached
)。通过slash-command"
答案 0 :(得分:6)
您正在做所有正确的事情,只需要更改订单。
立即响应原始请求并发出200 OK
响应。有关详细信息,请参阅this answer,但主要是:
ignore_user_abort(true);
ob_start();
echo('{"response_type": "in_channel", "text": "Checking, please wait..."}');
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("Content-Type: application/json");
header('Content-Length: '.ob_get_length());
ob_end_flush();
ob_flush();
flush();
然后使用curl制作Yoda API请求,正如您所做的那样
$response_url
的Slack,正如您所做的那样。答案 1 :(得分:2)
如果您正在使用FPM,那么这就是您想要的 - http://php.net/manual/en/function.fastcgi-finish-request.php
您的代码将如下所示......
<?php
$response_url = $_POST["response_url"];
$term = rawurlencode($_POST["text"]);
error_log("POST: " . print_r($_POST, 1));
$response = ["response_type"=>"in_channel", "text"=>"Checking, please wait..."];
echo json_encode($response);
header("Content-Type: application/json");
fastcgi_finish_request();
$ch = curl_init();
...
答案 2 :(得分:1)
从我所看到的in the documentation,您大致正确地做事。只需通过回显任何内容,您就已经传递了200 OK消息,因此无需明确地执行此操作。您应该检查以确保这不是服务器问题;是发布到有效的URL?不会因为重写规则而受到损害吗?
我已经对下面的代码进行了一些更改,包括一些调试将转到您的错误日志(默认情况下是Apache的错误日志)。试一试,至少您将获得更多调试细节。
<?php
$response_url = $_POST["response_url"];
$term = rawurlencode($_POST["text"]);
error_log("POST: " . print_r($_POST, 1));
ob_end_clean();
ob_start();
$response = ["response_type"=>"in_channel", "text"=>"Checking, please wait..."];
echo json_encode($response);
header("Content-Type: application/json");
header("Content-Length: " . ob_get_size());
ob_end_flush();
flush();
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://yoda.p.mashape.com/yoda?sentence=$term",
CURLOPT_HTTPHEADER => ["X-Mashape-Key: deMeGoBfMvmshQSemozTqJEY9z0jp1eIhuAjsnx9cQAQsHUifD"],
CURLOPT_RETURNTRANSFER => true
]);
$yodaresponse = curl_exec($ch);
curl_close($ch);
error_log("Yoda response: $yodaresponse");
$yodajson = json_encode([
"response_type"=>"in_channel",
"text"=>$yodaresponse
]);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $response_url,
CURLOPT_POST => 1,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => $yodajson
]);
$resp = curl_exec($ch);
curl_close($ch);
error_log("API response: $resp");
答案 3 :(得分:1)
另一种方法是使用带有短暂超时的curl请求来生成第二个PHP脚本。由于我的提供者对我的PHP环境施加了一些限制(例如没有进程生成),这是唯一对我有用的方法。
第一个脚本将在不久之后终止,并将HTTP OK发送回Slack。第二个脚本将继续运行,处理耗时的处理(例如调用外部API),最后将结果作为延迟响应发送到response_url
。
第一个脚本
这是您第一个脚本中的curl请求:
<?php>
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "second.php?redirect_url=$redirect_url");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 400); //just some very short timeout
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_exec($ch);
curl_close($ch);
/* send short response back to user, e.g. "Processing your request..." */
?>
超时的长度是任意的,但在我的测试中,一个非常短的超时(例如10ms)不起作用。
您还需要实现一种在两个脚本之间传输输入数据的方法,如图所示,并将request_url
作为URL参数传递。
最后,对于斜杠命令,Slack要求您将简短的响应发送回用户。
第二个脚本
这是您的第二个脚本的样子:
<?php
ignore_user_abort(true); //very important!
usleep (500000); //to ensure 2nd script responds after 1st
/* call external API */
/* send response back to Slack using response_url */
?>
语句ignore_user_abort(true);
是强制性的,以确保您的第二个脚本在卷曲超时后继续运行。
{0}的usleep
是为了确保第二个脚本在第一个脚本之后响应,但不是强制要求此解决方案起作用。
该示例基于&#34; Continue PHP execution after sending HTTP response&#34;的一个答案。问题
答案 4 :(得分:-1)
发布答案,因为我没有足够的声誉来发表评论......
我遇到了同样的问题,然后我意识到Slack以不同的方式处理请求和响应。具体来说,HTTP请求和响应的第一行不同。
HTTP请求示例:
GET /hello.htm HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
HTTP响应示例:
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache/2.2.14 (Win32)
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
Content-Length: 11
Content-Type: text/xml
Connection: Closed
hello there
如果您可以访问要在PHP中发送的原始字节(从未使用PHP,那么不熟悉),只需使其看起来像响应,而不是请求。否则,立即发送响应,然后执行您需要的工作,并使用新消息发送请求。这可以通过多种方式完成,其中一个由@ miken32概述,我选择在python中调用后台进程。