Slack の簡易エンドポイントを Amazon API Gateway で作った話

[ランサーズ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/lancers) の3日目です。
昨日は、[ランサーズの分析基盤(capybara)](https://engineer.blog.lancers.jp/2018/12/lancers-capybara/) についての記事でした。

本日は、ランサーズ社内で使用している Slack の独自エンドポイントについてお話しします。
Slack Webhoook の管理に悩んでいる場合は参考になるかもしれません。


## 概要
一言で表現すると「**Slack に投稿できる簡易エンドポイント**」です。
Slack 通知を気軽に実現するために作成しました。

- サーバやバッチから使うための Slack 通知エンドポイント
- POST でメッセージを投げつけるだけ
- Webhook URL やトークンなどを意識する必要なし
- Amazon API Gateway と Slack Incoming Webhook を活用

<img width="600" src="https://qiita-image-store.s3.amazonaws.com/0/144905/bb4821b3-9e1e-4111-a093-1c10df14fced.png">

&nbsp;
詳細な仕組みについては後述します。


## Slack 簡易エンドポイントの使い方
エンドポイントに POST リクエストを送信するだけです。
どんな手段・言語でもすぐに使えます。

### テキストだけを指定
最低限必要なパラメータは `text` だけで、未指定の項目にはデフォルト値が適用されます。

```
curl -XPOST https://xxxxxx.com/slack --data "text=通知のテストメッセージです。"
```
何も指定しない場合は、Slack テスト部屋にランサーズ君が通知してくれます。かわいい。
<img width="393" src="https://user-images.githubusercontent.com/24243541/46390139-47562700-c711-11e8-8ed3-4edd99d9a160.png">

### 名前とアイコンを指定
`username` や `icon_emoji` を指定すれば、アイコンや名前も変えられます。

```
curl -XPOST https://xxxxxx.com/slack \
--data "username=Testbot" \
--data "icon_emoji=:ghost:" \
--data "channel=#alert" \
--data "text=通知のテストメッセージです。"
```
<img width="262" src="https://user-images.githubusercontent.com/24243541/41633466-101a54ee-747a-11e8-8138-953c5199da1d.png">

### JSON 形式で送信
JSON の方が扱いやすい場面も多々あります。
同じパラメータを JSON として送り付けても受け付けます。

```
curl -XPOST https://xxxxx.com/slack \
--header "Content-Type: application/json" \
--data '{
  "username": "Testbot",
  "icon_emoji": ":ghost:",
  "channel": "#alert",
  "text": "通知のテストメッセージです。"
}'
```
<img width="262" src="https://user-images.githubusercontent.com/24243541/41633466-101a54ee-747a-11e8-8138-953c5199da1d.png">


## メリット
何よりも **簡単に使える** ことが一番の利点です。

- 通知内容だけをシンプルにサクッと送信できる
- Webhook URL を発行する手間が掛からない
- 各種ツールに Webhook URL や認証情報を埋め込まずに済む
- Webhook 経路の一括管理ができる


## デメリット
- Incoming Webhook 非対応の機能（画像送信など）は使えない

裏側を Slack API に置き換えることで、対応自体は可能です。


## Amazon API Gateway で実装
Slack 簡易エンドポイントは Amazon API Gateway で実装しました。
**受け付けたリクエストを Slack に横流しするだけ** なので、Lambda も使いません。

`Content-Type` によって以下のマッピングテンプレートを使い分けます。

### application/json
JSON 形式でリクエストが来た場合は、何も変えずにそのまま使います。

```:マッピングテンプレート
$input.body
```

### application/x-www-form-urlencoded
Form 形式でリクエストが来た場合は、リクエストボディを分解して JSON 形式に変換します。

```:マッピングテンプレート
{
#foreach($kv_str in $input.body.split('&'))
#set($kv = $kv_str.split('='))
  "$kv[0]" : "$kv[1]"#if($foreach.hasNext),#end
#end
}
```

&nbsp;
統合タイプを `HTTP` にした上で、Slack Incoming Webhook の URL を指定すると完成です。
<img width="640" src="https://qiita-image-store.s3.amazonaws.com/0/144905/331fe37d-ee8e-75c7-9f0a-760fc6d822cb.png">

細かいところではカスタムドメインやリソースポリシーのアクセス制限も設定していますが、割愛します。

&nbsp;
API Gateway しか使用しないため、運用作業不要・コストも非常に低く抑えられるのが特徴です。
1ヶ月に100万回呼び出したとしても `$4.25` だけで済みます。


## Slack 簡易エンドポイントの導入効果
Slack へ簡単に通知できるようになったため、
これまでメールや別の手段で通知していたものを Slack に置き換える流れが加速しています。

多い日には1日で1000件近く呼ばれるようになりました。
今後も、社内 Bot の増加とともにエンドポイントへのアクセスが増える見込みです。
<img width="320" src="https://qiita-image-store.s3.amazonaws.com/0/144905/beb269d2-8cae-7275-3ab9-186da0262fae.png">


## まとめ
- Slack へ簡単に通知するためのエンドポイントを作成しました
- POST リクエスト一つで通知できるため簡単に使えます
- API Gateway を活用して運用負荷＆コストの低減を図っています

今後は Slack API を使った再実装や、さらなる機能拡張などに取り組みたいと考えています。

&nbsp;
以上、[ランサーズ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/lancers) 3日目の記事でした。
明日は [inamuu](https://qiita.com/inamuu) さんの記事です。お楽しみに！