新しいHTTPメソッド QUERY(RFC 10008)を Hono + Bun で実装したサンプルAPIです。
QUERY は「ボディを持てる、安全でべき等なGET」という位置づけのメソッドで、GET の「状態を変えない・キャッシュできる」性質と、POST の「ボディで複雑な条件を渡せる」性質のいいとこ取りをしたものです。本リポジトリでは、ブログ記事の検索エンドポイントを題材に QUERY を実装しています。
- ランタイム: Bun
- Webフレームワーク: Hono
- バリデーション: zod + @hono/zod-validator
- Linter / Formatter: Biome
依存関係をインストールします。
bun install開発サーバー(ホットリロード付き)を起動します。
bun run devhttp://localhost:3000 で起動します。
$ curl -s localhost:3000/ping
pong| メソッド | パス | 説明 |
|---|---|---|
GET |
/ping |
疎通確認(pong を返す) |
OPTIONS |
/blogs |
対応メソッドと受け付けるボディ形式を返す |
QUERY |
/blogs |
ブログを検索する |
このエンドポイントが QUERY を受け付けるか、OPTIONS で確認できます。
レスポンスヘッダの Allow と Accept-Query で、対応メソッドと受け付けるボディ形式を宣言しています。
$ curl -s -X OPTIONS localhost:3000/blogs -i
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: QUERY, OPTIONS
Access-Control-Allow-Headers: Content-Type, Accept-Query
Allow: QUERY, OPTIONS
Accept-Query: application/json
Content-Length: 0JSONボディで検索条件を渡します。ボディのフィールドはすべて任意です。
| フィールド | 型 | 説明 |
|---|---|---|
query |
string |
タイトルに含まれる文字列で絞り込む |
limit |
integer |
取得する件数の上限 |
未知のフィールドは受け付けません(.strict())。
# 全件取得(空のJSONを渡す)
$ curl -s -X QUERY localhost:3000/blogs \
-H "Content-Type: application/json" \
-d '{}'
# 「入門」で検索して2件だけ取得
$ curl -s -X QUERY localhost:3000/blogs \
-H "Content-Type: application/json" \
-d '{"query":"入門","limit":2}'
{"blogs":[
{"id":1,"title":"Clojure入門","content":"こんにちは。Clojureの世界へようこそ。"},
{"id":5,"title":"GraphQL入門","content":"GraphQLはAPIの新しい形です。"}
]}| ステータス | 条件 |
|---|---|
200 OK |
検索成功 |
400 Bad Request |
ボディがスキーマに合わない(未知のキー、型不一致など) |
415 Unsupported Media Type |
Content-Type が application/json でない |
# スキーマにないキーを渡す → 400
$ curl -s -o /dev/null -w "%{http_code}\n" -X QUERY localhost:3000/blogs \
-H "Content-Type: application/json" -d '{"foo":1}'
400
# JSON以外のContent-Type → 415
$ curl -s -o /dev/null -w "%{http_code}\n" -X QUERY localhost:3000/blogs \
-H "Content-Type: text/plain" -d 'hi'
415src/
├── index.ts # ルーティング(app.on("QUERY", ...))
├── data.ts # サンプルデータ(ブログ10件)
├── domains/
│ └── blog.ts # Blog / Blogs ドメインモデル(検索・ソート・件数制限)
└── handlers/
└── blogs.ts # QUERY ハンドラ(バリデーション・415/400 処理)
# フォーマット
bun run format
# Lint(自動修正)
bun run lint
# フォーマット + Lint
bun run format:lint