📢

SendGridのイベントをSocket.IOでプッシュ表示する

2022/01/05に公開

SendGridのEvent Webhookでイベントを確認するとき、Request BinWebhook.siteのようなサイトをよく使います。同じようなものを自前で作りたいけど、サーバサイドで受信したPOSTデータをどうやってクライアント(ブラウザ)にプッシュ表示するんだっけ...と思って昔聞いたWebSocketやSSE(Server-Sent Events)を調べていたところSocket.IOを知りました。

試したところ簡単に実装できたのでまとめます。環境はdocker上のalpine linux 3.15.0&Node.js 17.3.0です。

app.js

まずはサーバサイドです。こちらで書いたapp.jsに対してSocket.IOのGet Startedのサーバサイドを参考に書きました。

app.js
const express = require('express');
const { createServer } = require('http');
const { Server } = require('socket.io');
const bodyParser = require('body-parser');

const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer);

app.use(bodyParser.json());
app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

app.post('/', (req, res) => {
    io.emit('message', JSON.stringify(req.body));
    res.sendStatus(200);
});

io.on('connection', socket => {
    console.log('connection');
    socket.on('disconnect', () => {
        console.log('disconnect');
    });
});

httpServer.listen(3000);

当初POST部分は以下のように書いていたのですが、SendGridのEvent WebhookはJSONオブジェクトの配列が入るため、何もしないとクライアント側では[object Object],[object Object]...のような表示になってしまうためJSON.stringfyで文字列に変換しました。(使い方あってるのかな...)

app.post('/', (req, res) => {
    io.emit('message', req.body);
    res.sendStatus(200);
});

index.html

クライアントのHTMLです。socket.io.min.jsはCDNのものを利用しました。pタグにサーバから受け取ったデータを追加するだけです。

index.html
<!DOCTYPE html>
<html>
  <head>
      <meta charset="utf-8">
      <title>SendGrid Event Webhook</title>
  </head>
  <body>
      <p id="message"></p>
      <script src="https://cdn.socket.io/4.4.0/socket.io.min.js" integrity="sha384-1fOn6VtTq3PWwfsOrk45LnYcGosJwzMHv+Xh/Jx5303FVOXzEnw0EpLv30mtjmlj" crossorigin="anonymous"></script>
      <script>
        const socket = io();
        var message = document.getElementById("message");
        socket.on('message', msg => {
            message.innerHTML += msg;
        });
        </script>
  </body>
</html>

実行結果

動作確認はこちらの手順でlocaltunnelを使ったローカル環境で行いました。

アクセスすると初めは何も表示されていない状態です。Event Webhookの「Test Your Integration」を押してPOSTデータを受信するとサーバからクライアント(ブラウザ)にプッシュ表示します。

これをどこかにホスティングすればRequestBinみたいに使えるはず。

Discussion