2016-03-24 5 views
8

Slack Customコマンドを使用しようとしていますが、Yoda Speak外部APIが応答するのに3秒以上かかるため、遅延メッセージの使用方法はあまりよく分かりません。Slack PHP API - タイムアウトエラーを回避する

私は次のように行われている:私の場合のたるみコマンド/Yodaを送信

  • reponse_urlを受けました。
  • postには、以下を応答URLに使用します。私はヨーダのAPIを呼び出すときに今
    • enter image description here

      $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); 
      
  • は、それが "タイムアウトに達した" 次のエラーを与えます。私は delayed responsesについて読んでいますが、ここからどのように進めるべきかはわかりません。
$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); 

私はまだ同じエラーが得る「ダーン - コマンドをスラッシュそれが動作しませんでした(エラーメッセージ:Timeout was reachedを)。スラッシュコマンドでコマンドを管理する」

+1

まだ遅延応答は試していませんが、ドキュメンテーションに「HTTP 200」(最大3000ms以内)で返信する必要があることが記載されています。後で同じ応答URLに返信する可能性があります。 –

+0

@Ciccioそれは私が理解していない部分です 私はすでに「確認してください、待ってください」という同等の200 OK応答です。私はあなたが "あなたは同じ応答URLに後で返信することができます"ということを理解していません。同じ 'response_url'をもう一度使うべきですか? – Vimalnath

+2

@Vimalnathあなたは「チェックしてください、待ってください」というメッセージを送信すると、スラックに対する200 OK応答に相当しません。あなたは** Slackが200でサーバーに送信する要求に応答する必要があります。 –

答えて

6

あなたは正しいことをしているだけで、順序を変更する必要があります。

  1. すぐに200 OK応答で元の要求に応答します。詳細については、this answerを参照してください、しかし、本質的に:あなたは

  2. をやっていると、あなたがヨーダの結果を持っていたら

    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(); 
    
  3. その後は、カールを使用してヨーダのAPIリクエストを行い、使用して$response_urlでスラックするためにそれらを送りますあなたがやっているようにカール。

+0

あなたの答えをありがとう、質問で私の更新されたコードをチェックできますか? 私は何かを見逃しても、私はまだ同じエラーが表示されます。 – Vimalnath

+0

私はコマンドラインのカールをスラッシュコマンドのURLに投稿することをお勧めします(例えば 'curl -H" Content-Type:application/json "--data @ body.json http:// localhost:8000/slash '、おそらく$ response_urlのためにhttp://requestb.in/を使ってください)、あなたは200がすぐにカールするかどうかを知ることができます。 – rcoup

+1

サウンドアプローチのように見えますが、残念なことにシームレスに機能しません。私はそれをテストしたが、それでもタイムアウトになります。 Slackのような継ぎ目は 'flush()'にもかかわらず要求を開いたままにします。 @rcoupあなたのアプローチをうまくテストしましたか? –

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"); 
0

コメントを投稿するには十分な評判がないので、回答を投稿する...

私は同じ問題を抱えていました。そして、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を使用したことがないので、慣れていない)にアクセスできる場合リクエストではなくレスポンスのように見えます。それ以外の場合は、すぐに応答を送信し、必要な作業を行い、新しいメッセージで要求を送信します。これはいくつかの方法で行うことができ、そのうちの1つは@ miken32によって概説されています。私はPythonでバックグラウンドプロセスを呼び出すためにオプトアウトしました。

0

もう1つのアプローチは、短いタイムアウトでカールリクエストを使用して、2番目のPHPスクリプトを生成することです。私のプロバイダは私のPHP環境にいくつかの制限を設けているので(これはプロセス産卵なしなど)、私にとってはこれが唯一の方法でした。

最初のスクリプトはすぐに終了し、HTTP OKをスラックに送り返します。 2番目のスクリプトは実行を継続し、時間のかかる処理(たとえば外部APIの呼び出し)を処理し、最後に結果をresponse_urlに遅延応答として送信します。

第一スクリプト

これはあなたの最初のスクリプトでカールリクエストです:

<?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)のでしたうまくいかない。

また、URLパラメータとしてrequest_urlを渡すように、2つのスクリプト間で入力データを転送する方法を実装する必要があります。

最後にスラッシュコマンドの場合、スラックはユーザーに短い応答を返す必要があります。

第二スクリプト

これがあなたの第二のスクリプトがどのように見えるかです:ignore_user_abort(true);はあなたの第二のスクリプトがカールタイムアウト後に実行し続けることを確認するために必須である

<?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 */ 
?> 

声明。

usleepの0.5秒は、2番目のスクリプトが最初の応答後に応答するようにすることですが、この解決策が機能するには必須ではありません。

この例は、「Continue PHP execution after sending HTTP response」という質問に対する1つの回答に基づいています。

関連する問題