ボクココ

個人開発に関するテックブログ

Twilio x AWS Lambda と API Gateway の連携

ども、@kimihom です。

このブログでは初登場の Twilio の話。 どんなことができるかは Twilio のリンク先に任せるとして、今回は実際に Twilio を利用している方のための TIPS を紹介しようと思う。

電話の可用性を高める

プログラムと連携した TwiML を書いていると、エラーが起きた時に心配になる。電話であるが故にエラーが起きてずっと利用できないとコミュニケーション手段が奪われるため、かなり痛い状況になってしまう。このような自体が起こりうるケースとしてはプログラムのバグで TwiML の書き方が間違えていたり、そもそもサーバー自体が落ちてしまっていた場合などだ。これらの問題が起きた時に迅速に検知し、対応できるようにするのはとても重要なことだ。

そこですぐにエラーが出たことを検知する仕組みを導入する必要があるのだけども、Twilio でデフォルトで提供している アラートトリガー は、期間を1日より細かく設定することができない。即座に対応することが困難である。また、連絡先としてメールアドレスかWebHookかを選べるのだが、このWebHookの形式と Slack の Incoming WebHook の形式は一致していないため、Slackに通知することもできない。

ということで Twilioの電話番号に紐付いた フォールバックURLというものを用いてエラーが起きた時に自動で通知する仕組みを構築する。

Twilioの仕組みとして各電話番号にはまず最初にリクエストを送る リクエストURLと、そのリクエストに失敗した場合に送るフォールバックURLの2つがあり、このどちらも自由に設定することが可能である。ここで大事なのは、リクエストURLとフォールバック URLの向き先は同じサーバーに向けてはいけない、という点にある。なぜなら、サーバー自体が落ちていたら、その時点でアウトだからだ。

ということで今回はフォールバックURLの指定先は Amazon API Gateway から AWS Lambda を起動するような構成にしようと思う。これにすればほとんど無料で通知の仕組みを導入できる。このような通知の仕組みを構築するのにはAmazon API Gateway と AWS Lambda のコンビネーションは理想の環境だ。以下にイメージ図を示す。

f:id:cevid_cpp:20151007193358p:plain

Slack の設定

Slack では Incoming Webhook を利用する。まずはこのインテグレーションをONにし、Webhook先のURLをコピーしておこう。https://hooks.slack.com/services/~~ のURLがそれだ。

AWS Lambda ファンクションの作成

本記事では Amazon API Gateway や AWS Lambda のセットアップなどの入門者的な内容は省略させていただいている。それらの内容はググったり公式ドキュメントを参照していただきたい。

今回は npm モジュールとして request を利用する。 index.js は以下のようになる。

var request = require('request');

exports.handler = function(event, context) {
  param = {
    text: "電話エラー発生!!\nAccountSid: " + event.param.AccountSid + ",\n ErrorUrl: <" + encodeURIComponent(event.param.ErrorUrl) + "|Link>,\nFrom: " + event.param.From + ",\nTo: " + event.param.To,
    icon_emoji: ":ghost:"
  };

  var url = "https://hooks.slack.com/services/T07777777/B0AAAAAAAAAAAAA";

  var options = {
    uri: url,
    form: "payload=" + JSON.stringify(param)
  };

  request.post(options, function(error, response, body){
    context.done();
  });
};

ここで重要なのは、Twilio はフォールバックURLに指定したサーバーに対して、 AccountSid をはじめ、エラーの起きたURLやFrom,To の電話番号など、重要な情報を投げてくれる点にある。これらをSlackに通知すれば、誰に影響が起きたのかすぐわかるし、問題解決が一気に早くなるだろう。

コードを保存したら後は通常通り index.js と node_modules をzip に固めて AWS Lambda にアップロードすればOK。

Amazon API Gatway の設定

問題はここからだ。フォールバック URL に URL をセットできるようにするために Amazon API Gatway を利用する。

まずは適当な名前でAPIを作成しよう。そして Create Method で GET を選択する。そして実行するのは 先ほど作成した AWS Lambda Function である。うまく設定できれば以下のような図に移るはずだ。

f:id:cevid_cpp:20151007195533p:plain

以下の手順で API Gateway のメソッドを設定していく。

  1. Integration Request をクリックし、Mapping Templatesのapplication/jsonを選択。その右側のInput Paththrough を Mapping Template に変えて以下のように記述する。
{
  "param": {
#foreach( $key in $input.params().querystring.keySet() )
    "$key": "$input.params().querystring.get($key)"#if( $foreach.hasNext ),#end
#end
  },
  "stage": "$context.stage"
}

f:id:cevid_cpp:20151007195852p:plain

  1. Integration Response を開き、200を開いてそこのMapping Template のContent-Type を application/xml に変更。さらにそこでエラー時の TwiMLを記載する。

f:id:cevid_cpp:20151007195955p:plain

  1. Method Response の Content Type を application/xml に変更する。

  2. Deploy API でデプロイする。

  3. そこで出来上がった URL をTwilio の電話番号のフォールバック URLに設定する。

以上で出来上がりだ。

デバッグ TIPS

バグの修正に役立つTIPSを最後に紹介する。

Twilio の管理ページではどのリクエストで失敗したのかをわかりやすく時系列で表示してくれているので、それをまず見てみよう。

具体的にはログイン後の ログ -> 通話のページだ。そのページ内にリクエストとレスポンスの結果がそれぞれ書かれているので、どこが悪かったのか把握できる。

AWS Lambda のログを確認しよう。

AWS Lambda で console.log で書き出した結果は、AWS Lambda のタブ内にある Monitoring の View logs in CloudWatch から参照できる。AWS Lambda側でのデバッグはここで console.log で確認しよう。

最終確認

最後に 通常の TwiMLを返すアプリケーションサーバー側でわざと例外を発生させるなどして、フォールバックURLにアクセスさせた時に、以下のようにSlack に通知がくれば完成だ。

f:id:cevid_cpp:20151007201141p:plain

終わりに

まだまだ Twilio と Amazon API Gateway を連携させた例は出回っていないが、本来 Twilio でTwiML を返すサーバーとして、Amazon API Gateway を選択する、というやり方はとても効果的だと考えている。今回はフォールバックURLとしてAmazon API Gateway を利用したが、通常のリクエストURLにAmazon API Gateway を利用する方法も全く問題はない。というよりわざわざ Twilio 用にサーバーを立てるくらいだったら、それで済ませた方がよっぽどいいケースの方が多いかと思う。

ぜひ今回の記事を参考に、 Twilio x Amazon API Gateway の組み合わせにチャレンジしてみていただけたら幸いだ。