0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Hono × Next.js】HonoでAPIを作って、Swagger UIで動作確認する

Posted at

久々の投稿です。
HonoでAPIを作って、Swagger UIで動作確認していきます。

プロジェクト作成

まずは公式ドキュメントに記載の通りにプロジェクト作成をします。

pnpm create hoto@latest todo-app

実行すると、実行環境を選べたりするのですが、今後Next.jsでフロントエンドを作っていく予定なので、Next.jsを選びました。
※デプロイまでしたい場合はVercelを選ぶといいようです。

ディレクトリ構造

プロジェクト内のappディレクトリを示します。

app
 ┣ api
 ┃ ┗ [...route]
 ┃ ┃ ┗ route.ts
 ┣ layout.tsx
 ┗ page.tsx

route.ts

そしてこれが初期に生成されてるAPIが実装してあるファイルです。
今回の記事では、とりあえずSwagger UIで動作確認することなので、ここに全部書いていきます

app/api/[...route]/route.ts

import { Hono } from 'hono'
import { handle } from 'hono/vercel'

export const runtime = 'edge'

const app = new Hono().basePath('/api')

app.get('/hello', (c) => {
  return c.json({
    message: 'Hello Hono',
  })
})

export const GET = handle(app)
export const POST = handle(app)

APIの実装

準備

OpenAPIのドキュメント生成に@hono/zod-openapiを使うので、まずインポートと生成するインスタンスを変更します。

import { OpenAPIHono, createRoute, z } from '@hono/zod-openapi' 
// Swagger UIで使用
import { swaggerUI } from '@hono/swagger-ui'

const app = new OpenAPIHono().basePath('/api')

メッセージの取得

色々書いてありますが、ほとんどはドキュメント生成用のものです。
動作としては、posts配列の中身を返すだけです。
zを使うことでバリデーションを行えます。

// メッセージを格納する配列
let posts: {message: string}[] = []

app.openapi(
 createRoute({
   method: 'get',
   path: '/messages',
   description: "メッセージを取得する",
   responses: {
     200: {
       description: 'Respond messages',
       content: {
         'application/json': {
           schema: z.array(z.object({
             message: z.string()
           }))
         }
       }
     }
   }
 }),
 (c) => {
   return c.json(posts)
 }
)

メッセージの投稿

先述のposts配列に格納するものです。
GETメソッドは異なり、requestという項目があり、posts配列の要素の型と同じになっています。

app.openapi(
 createRoute({
   method: 'post',
   path: '/messages',
   description: "メッセージを投稿する",
   request: {
     body: {
       required: true,
       content: {
         'application/json': {
           schema: z.object({
             message: z.string()
           })
         }
       }
     }
   },
   responses: {
     200: {
       description: 'メッセージを投稿しました',
       content: {
         'application/json': {
           schema: z.object({
             message: z.string()
           })
         }
       }
     },
   }
 }),
 (c) => {
   const newMessage = { message: c.req.valid
   ('json').message }
   posts = [...posts, newMessage]
   return c.json(newMessage)
 }
)

ドキュメントとSwaggerの公開

docメソッドでドキュメントを公開します。
ローカルで起動して、/api/docにアクセスするとjson形式のドキュメントが確認できると思います。また、/api/swaggerではSwagger UIで動作確認が行えます。

app.doc('/doc', {
  info: {
    title: 'An API',
    version: 'v1'
  },
  openapi: '3.1.0'
})

app.get('/swagger', swaggerUI({ url: '/api/doc' }))

まとめ

APIの実装からドキュメントの自動生成、Swagger UIへのAPI公開まで一連の流れを学習できました!(cursor様様ではありますが笑)
実務でもモヤモヤしてたところなので、活かせそうです。

疑問なのは、ドキュメント生成は楽だけど、これをエンドポイントごとに書くのも大変じゃないかなって思いました。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?