Hono Middlewareの基本
HonoにおけるMiddlewareは、ルートハンドラの前に実行される関数です。リクエストの検証や、後続の処理に必要な情報を追加するなど、共通処理の実装に使用されます。
Middlewareはapp.use()
メソッドを使って、特定のパス、または全てのパスに対して登録します。
import { Hono } from 'hono';
import { corsMiddleware } from '@/middlewares/corsMiddleware';
import { methodGuard } from './utils/methodGuard';
const app = new Hono();
// 1. 全てのパスに適用されるMiddleware
app.use('*', corsMiddleware);
// 2. 特定のパスパターンに適用されるMiddleware
app.use('/public/*', methodGuard(['GET']));
// ... ルーティングなど ...
export default app;
実行順序
app.use(path, middleware)
: 第一引数にMiddlewareを適用するパスを指定します。*
は全てのパスにマッチします。第二引数にMiddleware関数を渡します。- 実行順序: Middlewareは
app.use()
で登録された順番に実行されます。上記の例では、まずcorsMiddleware
が実行され、その後、パスが/public/
で始まるリクエストに対してのみmethodGuard
が実行されます。
実装例
より具体的なMiddlewareの実装を見ていきましょう。
1. CORS
外部ドメインからのAPIリクエストを受け付けるためには、CORSヘッダーの設定が必要です。これは、Hono公式のhono/cors
ミドルウェアを使用することで簡単に実現できます。
// middlewares/corsMiddleware.ts
import { cors } from 'hono/cors';
export const corsMiddleware = cors({
origin: (origin) => {
// ここで許可するドメインを判定するロジックを実装できます
// この例では全てのオリジンを許可
return origin;
},
allowHeaders: ['Content-Type', 'X-API-Key'],
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
});
このMiddlewareをapp.use('*', ...)
で全てのルートに適用することで、CORS設定を一元管理できます。
2. メソッドガード
特定のパスに対して、許可するHTTPメソッドを制限したい場合に有効です。Honoのfactory
にあるcreateMiddleware
を使用すると、型安全なMiddlewareを簡単に作成できます。
// utils/methodGuard.ts
import { createMiddleware } from 'hono/factory';
export const methodGuard = (allowedMethods: string[]) => {
return createMiddleware(async (c, next) => {
if (!allowedMethods.includes(c.req.method)) {
return c.json({ error: 'Method Not Allowed' }, 405);
}
await next();
});
};
3. APIキー検証
保護されたルートに、共通のAPIキーでのアクセス制限をかける例です。Middleware内でリクエストヘッダーを検証し、後続の処理に制御を渡すか、エラーを返すかを決定します。
// middlewares/apiKeyAuth.ts
import { createMiddleware } from 'hono/factory';
const SECRET_API_KEY = 'your-super-secret-key'; // 本来は環境変数から読み込みます
export const apiKeyAuth = createMiddleware(async (c, next) => {
const apiKey = c.req.header('X-API-Key');
if (apiKey === SECRET_API_KEY) {
// キーが正しい場合は次の処理へ
await next();
} else {
// 正しくない場合は401エラーを返す
return c.json({ error: 'Unauthorized' }, 401);
}
});
4.後続処理
このapiKeyAuth
を特定のルートグループに適用します。
// routes/protected.ts
import { Hono } from 'hono';
import { apiKeyAuth } from '@/middlewares/apiKeyAuth';
const app = new Hono();
// このグループのルート全てにAPIキー検証Middlewareを適用
app.use('/*', apiKeyAuth);
app.get('/status', (c) => {
// このハンドラは、apiKeyAuthミドルウェアの検証を通過した場合にのみ実行される
return c.json({ message: 'API is active and protected' });
});
export { app as protectedRoutes };