Cloudflare Workers + KV + honoで簡単なAPIサーバを作る
Cloudflare Workers + KV + honoで簡単なAPIサーバーを作ってみたくて、ebaというモックAPIを作成できるAPIサーバーを書いてみた。突然適当なメソッドと適当なレスポンスを返すAPIが欲しくなったときに使える。
使い方としては、1) 専用の名前空間を作って、2) 好きなエンドポイントを設定する、だけ。こんな感じ。
code:sh
# 名前空間の作成。パスワードも適当に設定しておく。
{"namespace": "your-unique-namespace", "password": "xxxxxxxx"}
# エンドポイントの作成
-H 'X-NAMESPACE:your-unique-namespace' \
-H 'X-PASSWORD:xxxxxxxx' \
-H 'X-REQUEST-TYPE:create' \
-d '{"url": "/hoge", "method": "GET", "statusCode": 200, "responseHeader": {"content-type": "application/json", "my-original-header": "XXX"}, "responseBody": {"msg": "Hello"}}'
{"message": "ok"}
これで名前空間とエンドポイントが作成された。あとは作成したエンドポイントを叩くだけ。X-NAMESPACEの指定だけ常に必要になるので注意。
code:sh
HTTP/2 200
content-type: application/json
my-original-header: XXX
{"msg": "Hello"}
技術
今回利用した技術としては下記。
開発コマンド: wrangler2
サーバ: Cloudflare Workers
KVS: KV
framework: hono
言語: TypeScript
ビルド: esbuild
テスト: jest
テスト環境: miniflare
あと以降は開発環境の設定・テスト環境の設定・デプロイ設定などのコーディング以外の部分の情報が少なめのところを簡単に書いておく。
開発環境設定
wrangler2のインストール
code:sh
$ npm install -g wrangler
init
code:sh
$ wrangler init my-worker
KVの設定
KVの作成と設定
code:sh
$ wrangler kv:namespace create "MY_KV"
$ wrangler kv:namespace create --preview "MY_KV"
code:wrangler.toml
// wrangler.toml
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2022-05-15"
kv_namespaces = [
{ binding = "MY_KV", id = "yyyyyyyyyyyyyyyy", preview_id = "xxxxxxxxxxxxxxxxx" }
]
テスト環境の整備
依存関係のインストール
code:sh
$ npm i -D miniflare
$ npm i -D jest jest-environment-miniflare
$ npm i -D esbuild esbuild-jest
$ npm i -D @types/jest
miniflareはCloudflare Workersのローカルシミュレータ。wrangler2.0からはwrangler dev --localとやると内部的にはminiflareが使われるようになっているらしい。明示的にinstallしているのはjestのtestEnvironmentとしてminiflareを使用したいので。jest-environment-miniflareも同じくtestEnvironment用。 jestの設定
code:js
// jest.config.js
module.exports = {
testEnvironment: "miniflare",
testMatch: [
"**/test/**/*.+(ts|tsx|js)",
"**/src/**/(*.)+(spec|test).+(ts|tsx|js)",
],
transform: {
"^.+\\.(ts|tsx)$": "esbuild-jest",
},
};
tsconfig.jsonにjestの@typesの追加
code:json
// tsconfig.json
{
"compilerOptions": {
...
"types": [
"@cloudflare/workers-types",
"@types/jest" // <- 追記
]
...
}
}
scriptsにコマンド追加
code:json
// package.json
{
...
"scripts": {
"start": "wrangler dev",
"publish": "wrangler publish",
"build": "esbuild --bundle --outdir=dist ./src/index.ts", // <- 追加
"dev": "wrangler dev --local", // <- 追加
"test": "npx jest --verbose" // <- 追加
},
...
}
開発
サーバーを書く
KVを使った簡単なサーバー、MY_KVというネームペースがwrangler.tomlでWorkerにバインドされているのでdeclare`してしまえばスクリプトからput/getができる。
code:index.ts
declare const MY_KV: KVNamespace;
addEventListener('fetch', (event: FetchEvent): void => {
event.respondWith(this.handleEvent(event))
})
async function handleRequest(request) {
const key = ${request.method}
await MY_KV.put(key, Hello, ${request.method})
const value = await MY_KV.get(key)
return new Response(message: ${value}, {
headers: { 'content-type': 'text/plain' },
});
}
ローカルで開発サーバを立ち上げる
code:sh
$ npm run dev
code:sh
$ curl -X GET localhost:8787
message: Hello, GET
$ curl -X POST localhost:8787
message: Hello, POST
参考
アプリのコードはhonoのexmaplesを参考にした。
自分のコードも汚いけど参考にはなるかも。
デプロイ
GitHub Actionsの設定
下記環境変数をGitHubに設定する。
CF_API_TOKEN
API Tokensで発行。Edit Cloudflare Workersというテンプレからほぼデフォルトのまま作成。 CF_ACCOUNT_ID
Cloudflare WorkersのダッシュボードのTOPからコピー。
.github/workflows/deploy.ymlは下記の通り。
code:yml
name: Deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14"
cache: "npm"
- name: Install Dependencies
run: npm ci
- name: Build
run: npm run build
- name: Publish
uses: cloudflare/wrangler-action@2.0.0
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
その他
wrangler1ではなくwrangler2を使う
wranglerはついこの前wrangler2がリリースされた。miniflareというローカルシミュレータが組み込まれていたり何かと使いやすくなっているので特にこだわりなければwrangler2を使うと良い。
honoの開発が活発すぎる問題
ほぼ毎日何かしら開発されていて、マイナーバージョンレベルだとアップデートがガンガン行われている。これ事態別に悪いことではないんだけどREADMEやexampleのアプリとの乖離がちょくちょく発生したりして最初混乱した。コードもそんなに大きいものではないので困ったらソースコードを読むほうが早い。
参照リポジトリが少ない
wrangler2系を使った参照実装になるようなWorkersのリポジトリがそんなに多くないのでここどう書いたら良いのだろう???というような時に我流になりがち。まぁまだこの前正式にリリースされたばかりだから仕方ないけど。公式DocsにもExampleが増えていくといいなと思った。
wrangler.tomlをリポジトリに含めていいのか
wrangler.tomlにはCloudflare Workersに関する設定を記述するのだが、account_idやkvのidなどを含めてそのままGitHubに公開しても良いのかがわからなかった。account_idに関しては含めても良いというissueコメントを発見したが、kv_namespaceのidなんかも公開してしまっていいのだろうか。他の人たちのwrangler.tomlをみてみるとそのままidを含めている人もいればwrangler.example.tomlのような形で公開していない人もいた。API Tokenさえ漏れなければ別に公開していても大丈夫なんだろうとは思うけどこの辺はドキュメントに書いて欲しいなと思った。自分は現状クレカも登録してないし課金されることもないと思うのでwrangler.tomlの情報はGitに含めて公開してある。そもそも趣味アプリなので困ったらすぐ消せば良いし。 リソース
Workersの公式Docs。Workers関連で困ったらここ。ここより詳しく書いてあるリソースはまだないと思う。
時雨堂の中の人のscrapメモ。Workersをキャッチアップしていくときに必要になる知識やハマりどころなんかが割と網羅的にまとめられておりありがたい。余談だけどvoluntasさんには何故かTwitterをブロックされていてちょっと面白かった。
hono。公式DocsのQuick Startにも掲載されているWorkersのweb framework。hono情報はリポジトリが1番詳しい、というかそれ以外の情報源がほぼないのでここをみるしかない。