Intereting Posts

Slack PHP API – избежать ошибки тайм-аута

Я пытаюсь использовать команду Slack Custom и не очень уверен, как использовать отложенные сообщения, поскольку Yoda Speak External API занимает больше 3 секунд, чтобы ответить.

Я сделал следующее:

  • Отправил команду slack /Yoda в моем случае и получил reponse_url .
  • Чтобы post URL-адрес ответа, выполните следующие действия.
 $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); 

введите описание изображения здесь

  • Теперь, когда я называю API Yoda, он дает следующую ошибку: «Тайм-аут был достигнут». Я читал о задержанных ответах, но не уверен, как мне исходить отсюда.
 $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-команде"

    Вы делаете все правильно, просто нужно изменить порядок.

    1. Ответьте на исходный запрос с ответом 200 OK немедленно. Подробнее см. В этом ответе , но по существу:

       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(); 
    2. Затем сделайте запрос API Yoda, используя curl, как вы делаете

    3. Когда у вас есть результаты Yoda, отправьте их в Slack на $response_url используя curl, как вы это делаете.

    Из того, что я вижу в документации , вы делаете вещи в основном правильно. Просто повторив что-нибудь, вы уже передаете сообщение 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"); 

    Если вы используете 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(); ... 

    Отправка ответа, поскольку у меня недостаточно репутации для публикации комментариев …

    У меня была та же проблема, и я понял, что 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.

    Другим подходом, который будет работать, является использование запроса на завивание с коротким таймаутом для создания второго скрипта 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, 250); //just some very short timeout curl_exec($ch); curl_close($ch); /* send short response back to user, eg "Processing your request..." */ ?> 

    Длительность тайм-аутов произвольная, однако в моих тестах очень короткий тайм-аут (например, 10 мс) не работал.

    Вам также потребуется реализовать способ передачи входных данных между двумя сценариями, как показано на примере передачи параметра request_url качестве параметра URL.

    Наконец, для команд slash 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,5 сек – это обеспечение того, чтобы второй скрипт отвечал после первого, но не обязательно для этого решения.

    Пример основан на одном ответе на вопрос « Продолжить выполнение PHP после отправки ответа HTTP ».