DenoのOakでミドルウェアを作成する方法
概要
Oakは、ミドルウェア(middleware)を使用して、リクエストとレスポンスの間で処理を実行する能力を持つフレームワークです。ミドルウェアは、リクエストオブジェクト、レスポンスオブジェクト、および次のミドルウェア関数へのアクセスを提供します。ミドルウェアは、Oakのルートハンドラ内で使用されます。
ここでは、以下のバージョンを使用して、Oakでミドルウェアを作成する方法を紹介します。
- Oak v9.0.0
- Deno v1.15.3
また、今回作成するコードは全て、以下のGitHubリポジトリに掲載しています。
https://github.com/wiblok/Oak.js
ミドルウェアの定義方法
Oak.jsでは、ミドルウェアを使用する主な方法は次のようになります。
- アプリケーションレベルミドルウェア
全体のアプリケーションに適用されるミドルウェアです。app.use()
を用いて定義します。
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use((context, next) => {
console.log('This is an application-level middleware');
next();
});
- ルーターレベルミドルウェア
特定のルート、もしくはルートグループに対して適用されるミドルウェアです。router.use()
を用いて定義します。
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
const router = new Router();
router.use((context, next) => {
console.log('This is a router-level middleware');
next();
});
app.use(router.routes());
app.use(router.allowedMethods());
これらのミドルウェアは、個々の要求がアプリケーションを通過する際に特定のポイントで機能を実行するのに役立ちます。それぞれのミドルウェア関数は、要求-応答サイクルを終了させるか、スタック内の次のミドルウェア関数に要求と応答オブジェクトを渡すかします。
アプリケーションレベルミドルウェアを作成する方法
以下の例では、myMiddleware
という名前のアプリケーションレベルのミドルウェアを作成します。
application.ts
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
const myMiddleware = async (context, next) => {
// ミドルウェアの処理
console.log('ミドルウェアの実行');
await next();
}
app.use(myMiddleware);
app.use((context) => {
context.response.body = { message: 'Hello, World!' };
});
await app.listen({ port: 8000 });
このコードは、Oakフレームワークを使用してDenoでWebサーバーを作成するためのものです。以下にコードの解説を箇条書きで示します。
import { Application } from "https://deno.land/x/oak/mod.ts";
- Oakフレームワークを
Application
という名前でインポートします。
- Oakフレームワークを
const app = new Application();
new Application()
を呼び出して新しいOakアプリケーションを作成し、app
変数に代入します。
const myMiddleware = async (context, next) => { ... }
myMiddleware
という名前の関数を定義します。- この関数はミドルウェアと呼ばれ、リクエストを処理するためにOakによって使用されます。
console.log('ミドルウェアの実行');
- ミドルウェア関数内の処理の一部として、コンソールに「ミドルウェアの実行」というメッセージを出力します。
app.use(myMiddleware);
app.use
メソッドを使用して、作成したミドルウェア関数(myMiddleware
)をOakアプリケーションに適用します。- これにより、全てのリクエストがこのミドルウェア関数を通過することになります。
app.use((context) => { ... });
app.use
メソッドを使用して、GETリクエストに対するルートハンドラを定義します。- アロー関数内の処理では、
context.response.body
プロパティを使用してJSON形式のレスポンスを送信しています。
await app.listen({ port: 8000 });
app.listen
メソッドを使用して、ポート8000でアプリケーションを起動します。
以下のコマンドを使用してリクエストを送信できます。
curl -X GET http://localhost:8000
ルーターレベルミドルウェアを作成する方法
以下の例では、myMiddleware
という名前のルーターレベルのミドルウェアを作成します。
routeMiddleware.ts
const myMiddleware = async (context, next) => {
// ミドルウェアの処理
console.log('ミドルウェアの実行');
await next();
}
export default myMiddleware;
routeMain.ts
import { Application } from "https://deno.land/x/oak/mod.ts";
import myMiddleware from './routeMiddleware.ts';
const app = new Application();
app.use(myMiddleware);
app.use((context) => {
context.response.body = { message: 'Hello, World!' };
});
await app.listen({ port: 3000 });
console.log('Server is running on port 3000');
このコードを実行すると、すべてのリクエストに対してミドルウェアが実行され、コンソールに ‘ミドルウェアの実行’と出力されます。
curl -X GET http://localhost:3000
組み込みミドルウェアを利用する方法
Oakフレームワークには組み込みのミドルウェアがあり、これらは特定の機能を提供します。例えば、以下のようなコードで静的ファイルを提供することができます。
builtin.ts
import { Application, send } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
// sendミドルウェアを使用して静的ファイルを提供する
app.use(async (context) => {
await send(context, context.request.url.pathname, {
root: `${Deno.cwd()}/public`,
});
});
await app.listen({ port: 3000 });
console.log('Server is running on port 3000');
このコードは、public
ディレクトリ内の静的ファイルを提供します。例えば、ブラウザでhttp://localhost:3000/sample.txt
にアクセスすると、public/sample.txt
が表示されます。
curl -X GET http://localhost:3000/sample.txt
サードパーティミドルウェアを利用する方法
Denoでは、deno.land/xから利用可能なサードパーティのミドルウェアを利用することができます。例えば、以下のようなコードでoak_middleware_logger
というログ出力用のミドルウェアを利用することができます。
deno install oak_middleware_logger
次に、このパッケージをアプリケーションに組み込むためのコードを記述します。
thirdparty.ts
import { Application } from "https://deno.land/x/oak/mod.ts";
import logger from "https://deno.land/x/o
ak_middleware_logger/mod.ts";
const app = new Application();
// loggerミドルウェアを使用してログを出力する
app.use(logger.logger);
app.use(logger.responseTime);
app.use((context) => {
context.response.body = { message: 'Hello, World!' };
});
await app.listen({ port: 3000 });
console.log('Server is running on port 3000');
このコードは、すべてのリクエストに対してoak_middleware_logger
ミドルウェアが実行され、それによってHTTPリクエストの詳細がコンソールに出力されます。
curl -X GET http://localhost:3000
エラーハンドリングミドルウェアの作成方法
エラーハンドリングミドルウェアは、他のミドルウェアから渡されたエラーを処理します。以下はエラーハンドリングミドルウェアの作成例です。
errorhandling.ts
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use(async (context, next) => {
try {
await next();
} catch (err) {
console.error(err.message);
context.response.status = 500;
context.response.body = 'Something went wrong';
}
});
app.use((context) => {
throw new Error('Something went wrong');
});
await app.listen({ port: 3000 });
console.log('Server is running on port 3000');
このコードでは、エラーハンドリングミドルウェアが実行された後にエラーをスローします。このエラーはエラーハンドリングミドルウェアによってキャッチされ、エラーメッセージがコンソールに出力されます。また、クライアントに対しては500エラー(Internal Server Error)とともにエラーメッセージが返されます。
curl -X GET http://localhost:3000