ガードと応答
ページは描画であって、応答を書きません。リクエストを通すかどうかと、応答にページ以外の何を付けるかは、ページより前に走る guard.ts が決めます。このページは、guard.ts の書き方、打ち切り方と通し方、responseHeaders() での添え方、guard が受け持つ範囲を説明します。
guard.ts
guard.ts はどの階層のディレクトリにも置け、そのディレクトリより下で答えるものの前に走ります。URL に沿って複数あれば、外側から 1 つずつ順に走ります。
src/routes/
layout.tsx
guard.ts
page.tsx
admin/
guard.ts
page.tsx
[id]/
page.tsx// src/routes/admin/guard.ts
import type { Guard } from '@k8ordo/server/runtime';
const guard: Guard<'/admin'> = ({ request }) => {
if (request.headers.get('cookie')?.includes('session=') === true) return;
return new Response(null, { status: 303, headers: { location: '/login' } });
};
export default guard;受け取るのは { request, params } です。request は届いたままの Request、params はそのディレクトリのパターンの params で、URL が運んだ文字列のままです。guard はどのレイアウトよりも上で走るので、スキーマが型を付ける前にいます。型は @k8ordo/server/runtime の Guard<P> で、生成された表も各 guard.ts をそのディレクトリのパターンで検査します。
打ち切るか、通すか
Response を返すと、それが答えになります。リダイレクトでも 401 でも 403 でもかまいません。その内側の guard も、下のページも走りません。何も返さなければ次の guard へ、最後の guard のあとは URL に答えるものへ渡ります。
応答に添える
通すときでも、最終的な応答に付けるものは添えられます。responseHeaders() は、何が答えるかにかかわらず最終的な応答が持つ Headers です。ページでも、そのペイロードでも、not-found でも、さらに内側の guard が打ち切った応答でも同じです。
// src/routes/guard.ts
import { responseHeaders } from '@k8ordo/server/runtime';
export default function guard() {
responseHeaders().set('x-content-type-options', 'nosniff');
}答えがすでに持っているヘッダーは置き換えます。responseHeaders() は guard が走っている間だけ使え、それ以外の場所では throw します。ページは描画で、応答を書く描画は 2 つ目のハンドラになってしまうからです。
next() は無い
ページを走らせてその答えを受け取り、書き換えてから返す next() はありません。ページはストリーミングで返り、本文を書き終える前にヘッダーが送られます。だから guard が決められるのは、ページが始まる前だけです。
guard が受け持つもの
guard は、そのディレクトリより下のすべての URL の前に走ります。
- ページと、クライアント遷移で取りに来るそのペイロード
- そのページへの
HEAD - そのページへ送られた Server Action
- 下にある
not-found.tsx。ルートの guard は、どれも答えない URL にも走ります
redirect.ts はどの guard よりも前に答えます。移転したディレクトリには、守るものが下にありません。
guard は Server Action そのものを守りません。アクションはどのページからでも呼べる関数で、呼んだページの URL へ送られます。アクションが要るものは、アクションの中で確かめます。 アクションとリクエスト
走る順番
guard は params のスキーマが URL を照合したあと、POST が運ぶ Server Action と描画より前に走ります。[locale] の下の guard は、URL が名指すロケールの中で走ります。
@k8ordo/static では
ファイルには守るリクエストがありません。@k8ordo/static は guard.ts を名指しで拒みます。ビルドでも vite dev でもです。