Open10
Remix on Cloudflare で KV を使ってセッションを管理する

このスクラップについて
このスクラップでは Hono Remix on Cloudflare Workers でキーバリューストアである KV を使ってセッションを管理する方法を調べてまとめていく。

Hono だとセッション管理のミドルウェアのデファクトスタンダードがないようなので一旦 Remix で考えることにしました。

まずは KV の使い方から調べよう

意外に Hono のセッションミドルウェアがない
できれば自作はしたくない。

まずは Remix で試そう
Remix には Session の機能があるので手始めにこちらから試してみよう。

プロジェクト作成
コマンド
pnpm create cloudflare@latest remix-session-scrap --framework remix --experimental

ドキュメント

コーディング
コマンド
touch app/sessions.ts
app/sessions.ts
import { createCookieSessionStorage } from "@remix-run/cloudflare";
type SessionData = {
userId: string;
};
type SessionFlashData = Record<string, never>;
const { getSession, commitSession, destroySession } =
createCookieSessionStorage<SessionData, SessionFlashData>({
cookie: {
name: "__remix_session_scrap",
domain: "localhost",
httpOnly: true,
maxAge: 60,
path: "/",
sameSite: "lax",
secrets: ["s3cret1"],
secure: true,
},
});
export { getSession, commitSession, destroySession };
app/routes/_index.tsx
import {
data,
type LoaderFunctionArgs,
type MetaFunction,
} from "@remix-run/cloudflare";
import { useLoaderData } from "@remix-run/react";
import { commitSession, getSession } from "~/sessions";
export const meta: MetaFunction = () => {
return [
{ title: "New Remix App" },
{ name: "description", content: "Welcome to Remix!" },
];
};
export async function loader({ request }: LoaderFunctionArgs) {
const session = await getSession(request.headers.get("Cookie"));
const userId = session.get("userId");
if (!userId) {
session.set("userId", "USER_ID");
}
return data(
{ userId },
{
headers: {
"Set-Cookie": await commitSession(session),
},
}
);
}
export default function Index() {
const { userId } = useLoaderData<typeof loader>();
return (
<dl>
<dt>User ID</dt>
<dd>{userId}</dd>
</dl>
);
}
これで 2 回目にアクセスした時に USER_ID と表示されるようになった。

名前空間の作成
コマンド
npx wrangler kv namespace create BINDING_NAME
BINDING_NAME にはどういうような名前を指定すれば良いんだろう、session とかで良いのかな?
実行に Cloudflare のストレージとデータベース > KV のページで作成を確認できた

wrangler.toml に追加
コマンド実行後に表示される設定内容を wrangler.toml に追記する。
wrangler.toml(追記)
[[kv_namespaces]]
binding = "BINDING_NAME"
id = "xxxx"