Astroのサーバーモードで、ページを横断してエラーハンドリングを行うにはMiddlewareを利用する方法がある。
await next()
で後続の処理が実行されるので、try-catchでエラーハンドリングを行うことができる。
// src/middleware.ts
import { defineMiddleware } from "astro/middleware";
export const onRequest = defineMiddleware(async (context, next) => {
try {
return await next();
} catch (e) {
// ここでエラーハンドリングを行う
throw e;
}
});
利用例
エラーログを通知したい場合
エラーが起きた時にエラーログを送信したい場合は、catchしたエラーを投げればよい。
Sentryのようなエラーログ収集サービスへ通知する際など。
(以下は notifyError という関数があるとする)
// src/middleware.ts
import { defineMiddleware } from "astro/middleware";
import { notifyError } from "./notifyError";
export const onRequest = defineMiddleware(async (context, next) => {
try {
return await next();
} catch (e) {
// エラーログを送信する
notifyError(e);
throw e;
}
});
特定のエラーで404ページを表示したい場合
特定のエラーが発生した場合に404ページを表示したい場合は、エラーの内容をチェックして404ページを返すことで実現できる。
例えばパスパラメータで指定されたデータがデータベースに存在しない場合に、500エラーを返す代わりに404ページを表示したい時など。
(以下ではそのような場合に NotFoundError というエラーがthrowされるとする)
// src/middleware.ts
import { defineMiddleware } from "astro/middleware";
import { NotFoundError } from "./errors";
export const onRequest = defineMiddleware(async (context, next) => {
try {
return await next();
} catch (e) {
// NotFoundErrorの場合は404ページを表示する
if (e instanceof NotFoundError) {
return context.rewrite("/404");
}
throw e;
}
});
別の方法
他にも、カスタム500ページを用意してエラーハンドリングを行う方法もある。
https://docs.astro.build/ja/basics/astro-pages/#カスタム500エラーページ
ただしMiddlewareを使う方法の方が汎用的だとは思う。
// src/pages/500.astro
---
import { notifyError } from "../notifyError";
interface Props {
error: unknown;
}
const { error } = Astro.props;
if (error instanceof NotFoundError) {
return Astro.rewrite("/404", 404);
}
notifyError(error);
---
500 Internal Server Error
雑感
Astro公式のミドルウェアのドキュメントをパッと見るだけではわからなかったのでメモ。
Middlewareのドキュメントをよく読むとレスポンスの内容を書き換えることができたりもするので、柔軟性が高いと感じた。