title | description | i18nReady |
---|---|---|
ミドルウェア |
Astroでのミドルウェアの使い方を学びます。 |
true |
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro'; import { Steps } from '@astrojs/starlight/components';
ミドルウェアにより、リクエストとレスポンスをインターセプトし、ページやエンドポイントがレンダリングされる直前に動的に振る舞いを注入できます。こうしたレンダリングは、ページが事前レンダリングされる場合にはビルド時におこなわれますが、オンデマンドにレンダリングされるページの場合は、ルートへのリクエスト時におこなわれます。
また、ミドルウェアを使って、すべてのAstroコンポーネントとAPIエンドポイントで利用可能なlocals
オブジェクトを変更し、リクエスト固有の情報を各エンドポイントとページで設定・共有することもできます。このオブジェクトは、このミドルウェアがビルド時に実行される場合でも利用できます。
-
このファイルの中で、
context
オブジェクトとnext()
関数を受け取るonRequest()
関数をエクスポートします。これをデフォルトエクスポートにしてはいけません。export function onRequest ({ locals, request }, next) { // リクエストからデータをインターセプトします // 必要に応じて、`locals`内のプロパティを改変します locals.title = "新しいタイトル"; // Responseか`next()`の結果を返します return next(); };
-
.astro
ファイルの中で、Astro.locals
を使ってレスポンスデータにアクセスします。--- const data = Astro.locals; --- <h1>{data.title}</h1> <p>この{data.property}はミドルウェアで設定しました。</p>
context
オブジェクトには、レンダリング中に他のミドルウェア、APIルート、.astro
ルートで利用可能な情報が含まれています。
これはonRequest()
に渡されるオプション引数で、locals
オブジェクトや、レンダリング中に共有されるその他のプロパティを含む場合があります。たとえばcontext
オブジェクトには、認証に使用されるクッキーを含められます。
context.locals
は、ミドルウェア内で変更可能なオブジェクトです。
このlocals
オブジェクトは、リクエスト処理のプロセスを通じて受け渡されていき、APIContext
とAstroGlobal
のプロパティとして利用できます。これにより、ミドルウェア、APIルート、.astro
ページ間でデータを共有できます。ユーザーデータなど、リクエスト固有のデータを各レンダリングステップをまたいで保持する際に役立ちます。
:::tip[インテグレーションのプロパティ]
インテグレーションは、locals
オブジェクトを介してプロパティを設定し、機能を提供する場合があります。インテグレーションを使用している場合は、そのドキュメントを確認して、プロパティを上書きしていないか、不要な操作をしていないかを確認してください。
:::
locals
には、文字列、数値、さらには関数やマップといった複雑なデータ型など、どんな型のデータでも格納できます。
export function onRequest ({ locals, request }, next) {
// リクエストからデータをインターセプトします
// 必要に応じて、`locals`内のプロパティを改変します
locals.user.name = "John Wick";
locals.welcomeTitle = () => {
return "おかえりなさい " + locals.user.name;
};
// Responseか`next()`の結果を返します
return next();
};
そして、任意の.astro
ファイル内でAstro.locals
によりこの情報を利用できます。
---
const title = Astro.locals.welcomeTitle();
const orders = Array.from(Astro.locals.orders.entries());
---
<h1>{title}</h1>
<p>この{data.property}はミドルウェアで設定しました。</p>
<ul>
{orders.map(order => {
return <li>{/* 各値を使って何かします */}</li>;
})}
</ul>
locals
は単一のAstroルートの中で生成・消滅します。ページルートがレンダリングされると、locals
はもう存在せず、その後また新しいものが作成されます。複数のページリクエストをまたいで保持されるべき情報は、別の場所に保存する必要があります。
:::note
locals
の値はランタイムに上書きできません。これをおこなうと、ユーザーが保存した情報がすべて消去される可能性があるためです。dev
モードにおいてAstroはこれを監視し、locals
が上書きされた場合にエラーをスローします。
:::
以下の例では、ミドルウェアを使用して「極秘情報」という文字列を「削除済み」という語に置き換えることで、変更されたHTMLをページにレンダリングできるようにします。
export const onRequest = async (context, next) => {
const response = await next();
const html = await response.text();
const redactedHtml = html.replaceAll("極秘情報", "削除済み");
return new Response(redactedHtml, {
status: 200,
headers: response.headers
});
};
defineMiddleware()
ユーティリティ関数をインポートして使用すると、型安全性を確保できます。
// src/middleware.ts
import { defineMiddleware } from "astro:middleware";
// `context`と`next`は自動的に型付けされます
export const onRequest = defineMiddleware((context, next) => {
});
JsDocにより型を記述している場合は、MiddlewareHandler
を使用できます。
// src/middleware.js
/**
* @type {import("astro").MiddlewareHandler}
*/
// `context`と`next`は自動的に型付けされます
export const onRequest = (context, next) => {
};
Astro.locals
内の情報に型を付け、.astro
ファイルとミドルウェアの両コードで自動補完を有効化するには、env.d.ts
ファイルでグローバル名前空間を宣言します。
/// <reference types="astro/client" />
declare namespace App {
interface Locals {
user: {
name: string
},
welcomeTitle: () => string,
orders: Map<string, object>
}
}
これにより、ミドルウェアファイル内で自動補完が有効になり、型安全性が確保されます。
sequence()
を使用して、複数のミドルウェアを指定した順序で連結できます。
import { sequence } from "astro:middleware";
async function validation(_, next) {
console.log("validationリクエスト");
const response = await next();
console.log("validationレスポンス");
return response;
}
async function auth(_, next) {
console.log("authリクエスト");
const response = await next();
console.log("authレスポンス");
return response;
}
async function greeting(_, next) {
console.log("greetingリクエスト");
const response = await next();
console.log("greetingレスポンス");
return response;
}
export const onRequest = sequence(validation, auth, greeting);
これにより、以下の順序でコンソールに出力されます。
validationリクエスト
authリクエスト
greetingリクエスト
greetingレスポンス
authレスポンス
validationレスポンス
ミドルウェアは、オンデマンドレンダリングされるすべてのページに対して実行を試みます。これにはAstroのデフォルト(空白)の404ページや、カスタムの404ページが含まれます。ただし、そのコードが実行されるかどうかはアダプターによって決定されます。一部のアダプターは、プラットフォーム固有のエラーページを代わりに提供する場合があります。
ミドルウェアはまた、カスタムの500ページを含む500エラーページを提供する前にも実行を試みます。ただし、ミドルウェア自体の実行中にサーバーエラーが発生した場合を除きます。ミドルウェアが正常に実行されない場合、500ページをレンダリングするためにAstro.locals
にアクセスすることはできません。
{/* TODO: このセクションはAPIリファレンスに移動する
src/middleware.js
からエクスポートされる必須の関数で、各ページやAPIルートのレンダリングの前に呼び出されます。2つのオプション引数、contextとnext()を受け取ります。onRequest()
は、Response
を返す必要があります。直接、またはnext()
を呼び出してください。
レンダリング処理中に、他のミドルウェア、APIルート、.astro
ルートで利用可能な情報を含むオブジェクトです。
これはonRequest()
に渡されるオプション引数で、locals
オブジェクトや、レンダリング中に共有されるその他のプロパティを含む場合があります。たとえばcontext
オブジェクトには、認証に使用されるクッキーを含められます。
これはAPIルートに渡されるcontext
オブジェクトと同じものです。
Request
のResponse
をインターセプトする(読み取り、変更を加える)か、ミドルウェアのチェーン内の「次の」ミドルウェアを呼び出してResponse
を返すための関数です。たとえばこの関数を用いて、レスポンスのHTML本文を変更できます。
これはonRequest()
のオプション引数で、ミドルウェアが返す必要のあるResponse
を提供します。
ミドルウェア内で変更可能な、Response
からのデータを含むオブジェクトです。
このlocals
オブジェクトは、リクエスト処理のプロセスを通じて転送されていき、APIContext
とAstroGlobal
のプロパティとして利用できます。これにより、ミドルウェア、APIルート、.astro
ページ間でデータを共有できます。ユーザーデータなど、リクエスト固有のデータを各レンダリングステップをまたいで保持するために役立ちます。
locals
は単一のAstroルーティング内で生成・消滅します。ルーティングされたページがレンダリングされると、locals
はもう存在せず、その後また新しいものが作成されます。複数のページリクエストをまたいで保持されるべき情報は、別の場所に保存する必要があります。
:::note
locals
の値は実行時に上書きできません。それをした場合、ユーザーが保存した情報がすべて消去される可能性があるためです。dev
モードにおいてAstroはこれを監視し、locals
が上書きされた場合にエラーをスローします。
:::
ミドルウェア関数を引数として受け取り、渡された順序で実行する関数です。
Astroミドルウェアで使用可能なAPIContext
を作成するための低レベルなAPIです。
この関数は、Astroミドルウェアをプログラムから実行する目的で、インテグレーションとアダプターから使用できます。
任意の値を受け取り、それをシリアライズした文字列を返す低レベルなAPIです。値をシリアライズできない場合、この関数はランタイムエラーをスローします。 */}