serverlessでslackbotローカル開発環境構築 - localtunnelでURL公開編 -

#何を作ろうとしている
slack apiフレームワークのboltをAWS Lambda上で動かして、さらにはDynamoDBとかも連携したSlackbotを作ろうとしている。

### 前回までのあらすじ

[serverlessでslackbotローカル開発環境構築 - serverless-offline編 -](https://qiita.com/herishiro/items/ea501ea48268f48b0ee1)

serverless-offlieを使って、ローカルにAPI GatewayとLambdaのエミュレーターを立ち上げることに成功しました。
次はそこで発行されたローカルエンドポイント(`http://localhost:3000/dev/slack/events`)をWEB上に公開して、実際のSlackからのリクエストを受け取れるようにします。

そのために当初ngrokを使っていたのですが、今はlocaltunnelを使っています。

##Localtunnelとは
https://localtunnel.github.io/www/
ローカルで立ち上げているサーバーをWEB上に公開できる。
slack apiのチュートリアルで使われているngrokと似たようなサービス。

###Localtunnelに切り替えた理由

**ngrokを再起動するたびに公開URL変わるのダルい･･･ダルくない？**

というわけで固定ドメインが使いたい、ngrokは有料プラン、月5ドルの年間契約
アマプラと一緒か、う～ん(比べる必要無し)
ということで代替サービスを探しました。

この記事を参考に。
[Top 4 BEST Ngrok Alternatives In 2020: Review And Comparison](https://www.softwaretestinghelp.com/ngrok-alternatives/)

まず**Serveo**は使おうとしたら向こうのサーバー落ちてるっぽいしあまりにも安定しないという噂があったので除外
**Pagekite**は条件なかなか良さそうでしたが、自分がpythonになじみが無いので、
とりあえずLocaltunnelから試してみたら全く問題なかったのでLocaltunnelを使っています。

###nigrokと比較したLocaltunnelの機能

複数同時にトンネルを立ち上げる機能が無いのがLocaltunnelの弱みですね。私は今のところ使わないので良いんですが。
ドキュメンテーションがないのは、必要ないくらいシンプルなので全然問題なしです。

| サービス名 | Authorization |HTTP / HTTPS, SSH | 使い方 | 有料/無料プラン | サブドメイン |
|:-:|:-:|:-:|:-:|:-:|:-:|
| Ngrok  | ユーザーはログインしてauthトークンの発行を求められる  | 3つともサポート  | ngrok実行ファイルから(またはライブラリからnode.jsを使って)  | 有料プランあり。無料には制限があるものの機能は充実 | 有料プランでサポート |
| Localtunnel  | authトークンは不要。nodeパッケージをインストールするだけで使い始められる | http/httpsをサポート  | node.jsから実行するだけ。例：lt --port 3000  | 無料のみ  |　無料。利用可能な文字列を値として与えればサブドメインで開始される　|

| サービス | 設定ファイル | マルチトンネル | ドキュメンテーション | プラットフォーム |
|:-:|:-:|:-:|:-:|:-:|
| Ngrok  | yamlファイルでトンネルの定義や実行を設定できる  | 設定ファイルを使うことで可能  | よくメンテされている  |  全てのプラットフォームに対応 |
| Localtunnel | 設定ファイルなし  | サポート無し  | ドキュメンテーション無し   |  全てのプラットフォームに対応 |

##Localtunnelの使い方

死ぬほど簡単です

**1. globalインストールして**

```bash
npm install -g localtunnel
``` 

**2. 実行するだけ！**

ドメインを指定せずランダム文字列URLで公開する場合：

```bash
lt --port 8000
```

サブドメインを指定する場合：
例えば`https://mynodejsapp.loca.lt`というURLにしたければこうです。

```bash
lt --port 3000 --subdomain mynodejsapp
```

あとは今回の場合そのURLに`dev/slack/event`というパスを付け足せば、slackからのリクエストをboltで処理できます。

##debugについて
これで晴れてslackからのリクエストを受け取れるようになったので、デバッグしやすくする方法について

###serverlessのdebugモード

>Unix: export SLS_DEBUG=*

>Windows: SET SLS_DEBUG=*

開発を始める前に環境変数に上記のように設定をすることで、デバッグモードに出来ます。
環境変数だからymlファイルのenviromentsに設定できるのかな？と思って調べたんですが、出来ないみたい。

###invokeされるLambda関数

前回の記事にてserverless-offlineでもLambda.invokeを使う方法を紹介したんですが、
実際のところ非同期でinvokeしているせいか、呼び出された関数側はconsole.logなどが出来ません。
なので、ローカル環境で実行されている時にtrueになるIS_OFFLINE環境変数を利用して、ローカルの時はinvokeせず直接呼び出すようにコードを修正しました。

```ts
  async echo({ command, ack }) {
    if (process.env.IS_OFFLINE === "true") {
      ack();
      invokedEventHandler.echo({ payload: command })
    } else {
      const lambda = new Lambda();
      let body = await getInvokedEventBody("echo", command)
      const params: AWS.Lambda.InvocationRequest = {
        InvocationType: "Event", // async invocation
        FunctionName: process.env.INVOKE_FUNCTION!,
        Payload: JSON.stringify(body),
      };
      const lambdaInvocation = await lambda.invoke(params).promise();
      await checkResponse(lambdaInvocation)
      ack();
    }
  }
```

こんな感じで…（ack()はslack boltのリクエスト受け取り確認用のメソッドです）

---
あとはステップ実行してデバックする設定とかslack bolt側でのデバックモードなんかも使ってみたいのですが、
とりあえず一通りの環境が出来たので、dynamoDBの使い方やwebpackを使ってlambdaにデプロイする内容を制御すると実行速度が速くなるという噂が本当かを勉強してまた記事にしたいと思います。
おわり