🤖

ngrokとPythonでWebhookを受信してjson出力

2022/06/15に公開

背景

私が所属するチームでは海外のとあるSaaSプロダクトを取扱してます。
そのSaaSでは、利用上発生するイベントをトリガーにWebhookを実行することができます。
今回はそちらを簡単に受信してファイル出力するところまでを目指します。

利用するもの

  • ngrok(エングロック)
  • Python
  • 某SaaSのWebhook(json形式でPOSTされます)

PythonでWebhookを受けるローカルサーバーを立てる

サーバーに到達したリクエストを処理するため、http.serverクラスのBaseHTTPRequestHandlerを利用します。
https://docs.python.org/ja/3/library/http.server.html

do_POST()を主に使っていきます。
私は以下のような感じで書きました。
POSTされる内容(Request Payroad)自体がjson形式なので、そのままファイル出力してます。
ターミナル等で実行しておきます。

wbhkReceiver.py
# -*- coding:utf-8 -*-
import http.server
import socketserver
import datetime
from urllib.parse import parse_qs, urlparse

class MyHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        print('path = {}'.format(self.path))
        parsed_path = urlparse(self.path)
        print('parsed: path = {}, query = {}'.format(parsed_path.path, parse_qs(parsed_path.query)))
        print('headers\r\n-----\r\n{}-----'.format(self.headers))
        content_length = int(self.headers['content-length'])
        
        #Body書き出し
        now = datetime.datetime.now()
        file_name = 'wbhk_out_' + now.strftime('%Y%m%d_%H%M%S') + '.json'
        req_body = self.rfile.read(content_length).decode("utf-8")
        with open(file_name, 'w') as f:
            f.write(req_body)
        
        self.send_response(200)
        self.send_header('Content-Type', 'text/plain; charset=utf-8')
        self.end_headers()
        self.wfile.write(b'Hello from do_POST')

with socketserver.TCPServer(("", 80), MyHandler) as httpd:
    httpd.serve_forever()


ngrok

ngrokはローカルホストで稼働するアプリケーションなどを外部公開してくれるサービスです。
わざわざWebサーバー組んだりサーバーレス使ったりっていう手間なくWebアプリが公開できちゃうんですね。お手軽な範囲でしたら無償で使えます。
https://ngrok.com/

インストール

まずはサインアップ後、nrgokをダウンロードします。Windows/Mac/Linux/FreeBSDに対応しているようです。私はWindowsで利用しました。
コンソールにログイン後、以下の画面の赤枠部分にトークンが表示されています。

実行準備

ガイドの通りコマンドを叩いてもよいのですが以下の記事を参考にbatファイルを作成しました。
https://qiita.com/mmurasawa/items/e508a6b04b5f15f155f9

作成したbatファイルは以下の2つです。順に実行します。

1_auth.bat
ngrok authtoken {YOUR_TOKEN_HERE}
2_80listen.bat
ngrok http 80



2_80listen.batを実行すると、以下のように表示されます。
赤枠部分、[https://xxx.jp.ngrok.io] の部分が要はWebhook側から見たエンドポイントのURLになります。ですので、Webhook側(渡しの場合はSaaSサービス)に設定してあげましょう。

テスト・確認

Webhook側からPOSTがあると、Pythonを実行しているターミナルでは以下のような感じで受信状況が分かります。

$ python .\wbhkReciever.py
path = /
parsed: path = /, query = {}
headers
-----
Host: hogehoge.jp.ngrok.io
User-Agent: Java/11.0.11
Content-Length: 699
Accept: text/plain, application/json, application/cbor, application/*+json, */*
Content-Type: application/json
hoge-Header1: Val_hoge-header
hoge-Header2: hogehogehoge
Traceparent: hhogeee
X-Forwarded-For: 11.222.333.44
X-Forwarded-Proto: https
Accept-Encoding: gzip

-----
127.0.0.1 - - [15/Jun/2022 10:11:12] "POST / HTTP/1.1" 200 -



ngrokでもWeb Inspection Interfaceが提供されてまして、受信状況を確認することができます。ngrokのドキュメントに記載があります。



http://localhost:4040 にアクセスすると、以下のような感じで確認することができます。

便利ですね!

まとめ

Webhookや、httpリクエストによるGET/POSTの処理を気軽にテストしたいときなどに非常に便利なツールです。無償で使える一方、より高機能且つエンタープライズ向けのプランもあるようです。

Discussion