アルパカ三銃士

〜アルパカに酔いしれる獣たちへ捧げる〜

ZEIT Now v2 を使った Serverless アプリケーションを Go で実装した

TL;DR

実装

最近自分のための Slack workspace を作ったんだけど、一人だとやっぱり寂しいので誰かを招待したいなと思って Slack の招待フォームを作ることにした。

そこで前から気になってた Serverless を開発するためのプラットフォームである ZEIT Now を使ってみることにした。

zeit.co

そして更に、生まれて初めて reCAPTCHA も使った。今回は reCAPTCHA については触れない。

始めに、いつも通り Go でアプリケーションを作るときの感じで http.ServeMux を使って自分でハンドラを作って...とやっていたが、デプロイ後のパスのルーティングが失敗してしまった。(resource not found などが表示される)

色々調べてみると now.json を使ってルーティングを定義してあげると良さそうだったので、その方向でコードを修正すると上手く動いてくれた。

今のプロジェクトのディレクトリ階層はこんな感じ。(まだ綺麗にしてないので名前が雑)

.
├── LICENSE
├── README.md
├── go.mod
├── go.sum
├── index
│   └── index.go
├── internal
│   ├── invitation
│   │   ├── invite_handler.go
│   │   ├── response.go
│   │   └── slack_invitation.go
│   ├── ip
│   │   ├── normalize.go
│   │   └── normalize_test.go
│   ├── recaptcha
│   │   └── recaptcha.go
│   └── slack
│       └── invite.go
├── invite
│   └── invite.go
├── main.go
└── now.json

7 directories, 15 files
  1. internal ディレクトリにハンドラのロジック部分を記述する。
  2. main.go はローカル環境で試すためにある。Production では不要なので .nowignore に記述してデプロイしないようにしてる

  3. invite, index ディレクトリはそれぞれハンドラを意味する。

実際にこれらのディレクトリ配下のコードはこれだけになる。

package invite

import (
    "net/http"

    "github.com/Code-Hex/slack-invitaion/internal/invitation"
)

var h = invitation.New()

func Handler(w http.ResponseWriter, r *http.Request) {
    h.ServeHTTP(w, r)
}

どうやら呼ばれる関数のフォーマットが func Handler(w http.ResponseWriter, r *http.Request) という形で決まっているらしいのでこのように記述した。

今度はルーティングを定義するファイル now.json をみる。

{
    "name": "slack-invitation",
    "version": 2,
    "builds": [
        { "src": "/index/*.go", "use": "@now/go" },
        { "src": "/invite/*.go", "use": "@now/go" }
    ],
    "routes": [
        { "src": "/", "dest": "/index/index.go" },
        { "src": "/invite", "dest": "/invite/invite.go" }
    ],
    "env": {
        "SLACK_API_TOKEN": "@slack-api-token",
        "SLACK_SUBDOMAIN" :"@slack-subdomain",
        "GOOGLE_CAPTCHA_SECRET" : "@google-captcha-secret"
    }
}
  • builds には build する対象のファイルを記述する
  • routes でハンドラになる対象の Go のファイルを指定する必要がある
  • env で環境変数を指定でき、 @~ で始まっているのは now secrets add google-captcha-sitekey VALUE のようにシークレットな値を登録することでそこから読み出すことが可能になる

ちなみに Go 1.12 が動いていて依存関係の解決に go.mod を使うらしいので追加した。

一旦完成

実装完了後の様子が下記で確認できる。

Join code-hex workspace on Slack!

ZEIT Now で Go の扱いはいまだに alpha 版となっているので知見が少なかった。なのでこれが誰かの役に立てると嬉しいなと思い残すことにした。