🐴

Webhookのテストにはngrok

2022/08/13に公開

背景

LINE CHAT BOT を開発していると、実装が正しく動いているかどうかをテストしたいが、その都度 Heroku へデプロイするのも面倒だなぁという場面に何度も遭遇する。

Webアプリの挙動確認であれば、ローカルサーバを立てることで簡単にテストできるのだろうが、LINE BOT だとそうはいかない。なぜなら、LINE Messageing API は 外部(LINEプラットフォーム) から ボットサーバのWebhook URL へとイベントが送信され、それに応じてユーザにレスポンスを返すという形式だからだ。

例えば、今回利用したフレームワーク Flask では、hostを0.0.0.0に設定してローカルサーバを起動してやれば、外部のネットワークからのアクセスを許可することができる。
https://flask.palletsprojects.com/en/2.2.x/quickstart/#a-minimal-application

Externally Visible Server
If you run the server you will notice that the server is only accessible from your own computer, not from any other in the network. This is the default because in debugging mode a user of the application can execute arbitrary Python code on your computer.
If you have the debugger disabled or trust the users on your network, you can make the server publicly available simply by adding --host=0.0.0.0 to the command line:
$ flask run --host=0.0.0.0
This tells your operating system to listen on all public IPs.

しかし、もう一つ問題がある。それは、Webhook URL には、HTTPS で通信可能なエンドポイントを設定しないといけないこと。

ngrokはこれらの問題を解決してくれる。

ngrokとは

ngrok(エングロック)はローカルサーバを外部ネットワークに簡単に公開できるトンネリングツールである。http://{ランダムな文字列}.ngrok.ioのような公開URLを設定し、そのURLへのをリクエストをlocalhostにフォワーディングしてくれる。httpsによる通信が可能な公開URLも作成できる。
https://ngrok.com/product

ngrokの導入/使い方

macOSであれば Homebrew を使って、ngrok を簡単にインストールできる。

Terminal
$ brew install ngrok

利用するときは、まずローカルサーバを立ち上げ、同一のポート番号で

Terminal
$ ngrok http [ポート番号]

とやってやるだけ。

すると、

Terminal
ngrok                                                                 (Ctrl+C to quit)
                                                                                                                                                    
Visit http://localhost:4040/ to inspect, replay, and modify your requests                                                                           
                                                                                                                                                    
Session Status                online                                                                                                                
Session Expires               1 hour, 51 minutes                                                                                                    
Terms of Service              https://ngrok.com/tos                                                                                                 
Version                       3.0.6                                                                                                                 
Region                        Japan (jp)                                                                                                            
Latency                       23ms                                                                                                                  
Web Interface                 http://127.0.0.1:4040                                                                                                 
Forwarding                    https://f02c-92-202-33-104.jp.ngrok.io -> http://localhost:5002                                                       
                                                                                                                                                    
Connections                   ttl     opn     rt1     rt5     p50     p90                                                                           
                              0       0       0.00    0.00    0.00    0.00

となって、Forwarding に公開URLが表示される。(今回であれば、https://f02c-92-202-33-104.jp.ngrok.io -> http://localhost:5002)

ngrokの注意点

  1. サブドメインの固定化
    ngrokが公開するURLのサブドメインは

    • ランダムな文字列
    • 立ち上げるたびに変わる

    という特徴があるが、ngrokにサインアップして、authtokenを発行することでサブドメインの固定化ができるらしい。有料プランに加入しないといけないかも??

  2. セキュリティリスク
    URLを異なるネットワークから誰でもアクセスできるような形で公開している以上、セキュリティ面を考える必要が出てくる。→ Basic認証の導入

    ngrokでは、上の 1.サブドメインの固定化 でも触れた authtoken を発行して、

    Terminal
    ngrok http -auth="username:password" [ポート番号]
    

    で起動することで、usernamepasswordを利用したBasic認証を設定することができる。

Discussion