はじめに
こんにちは、H×Hのセンリツ大好きエンジニアです。(同担OKです😉)
今回は、運用にお金を使いたくない人向けの味方「Vercel Functions」にステートレスなGoのAPIサーバをデプロイする方法をまとめました。
前提として、Vercel Functionsのデプロイに向いているものは以下の条件にクリアしたものになると思います😇
- ステートレス(セッション管理などをしない)
- 小規模なAPIサーバ
- 一回のデータ取得に時間が掛からない
セットアップ
- Vercelのアカウント登録
- Vercel CLIのインストール
- npmの場合、
npm i -g vercel
- npmの場合、
- Vercelにログイン
vercel login
APIエンドポイント作成
ディレクトリ構成
これを元に、ご自身で構成を変えていただければと思います🫣
.
├── api # エンドポイント用
│ ├── articles # APIの例
│ │ └── index.go
│ └── index.go # 接続確認用
├── APIエンドポイントから実行される関数
│ ├── 様々
│ └── 色々
├── go.mod
├── go.sum
└── vercel.json # 設定ファイル
APIエンドポイント
まずは、Vercel Functionsが正しく動作するかの確認用に、/api/index.go
を作成します。
package api
import (
"fmt"
"net/http"
)
func Handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "<h1>Hello Vercel Functions!</h1>")
}
そして、各種エンドポイントを作成します。
動かす関数は用意しておいてください。
今回は、ルーティングと同じようにディレクトリを分けてます🥹
package articles
import (
"net/http"
)
func Handler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
ArticlesPerPage(w, r) // 実行する関数はあらかじめ用意しておく
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
設定ファイル作成
基本的に、デプロイするディレクトリのルートに設置します。
{
"build": {
"env": {
"GO_BUILD_FLAGS": "-ldflags '-s -w'"
}
},
"rewrites": [
{ "source": "/api", "destination": "/api" },
{ "source": "/api/articles", "destination": "/api/articles" }
],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Access-Control-Allow-Origin", "value": "CORSを許可するURLを載せる" },
{ "key": "Access-Control-Allow-Methods", "value": "GET, OPTIONS" },
{ "key": "Access-Control-Allow-Headers", "value": "Content-Type, Authorization" }
]
}
]
}
ここで注意して欲しいのですが、リファレンスにあるroutes
は既に非推奨なので、rewrites
を使用してルーティングを行います。🤯
(クエリパラメータを受け取るエンドポイントでも、特に意識せず上記のようにパスだけルーティングしても大丈夫です)
また、このAPIサーバのCORS設定はheaders
で設定します。
(headers
を使用しないとCORSエラーになるので要注意!)
デプロイ
本番環境にデプロイをする場合、以下のコマンドを入力します。
vercel --prod
Error: queryA EREFUSED api.vercel.com
が発生する場合、DNS設定を見直したり、接続しているWi-Fiを変更してみてください。
デプロイ後、アクセスすると正しい挙動になっているか確認します。
api/articles
を入力してみます。
きちんと返ってきました。。。嬉しすぎて言葉が出ません。。。😮
注意点
POSTメソッドを行う場合、ブラウザによるCORSポリシーの一環であるプリフライトリクエスト(OPTIONSメソッド)が送信されてしまいます🥶
そのため、以下のように適切なCORSヘッダーを返すことで、POSTリクエストが正しく行われるようにします。
package articles
import (
"net/http"
)
func Handler(w http.ResponseWriter, r *http.Request) {
// OPTIONSリクエストへの対応
if r.Method == http.MethodOptions {
w.WriteHeader(http.StatusOK)
return
}
switch r.Method {
case http.MethodPost:
// 何かしらのPOSTメソッド関数
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
おわりに
今回は、節約したいエンジニアにとって素晴らしいツールである、Vercel Functionsの使用法を紹介しました。🥸
ですが、無料枠だと一回の関数が10秒以内に完了しないとtime out
エラーになってしまうので、使用前に関数を分解する or 別のデプロイ先(AWS Lambdaなど)を検討する方が良いかと思います🥹