ヘッダー & セッション認証
認証がないプロジェクトではcreateHttpClientのみを使用し、必要な場合にのみHeaderStoreとセッション認証を付けます。
このページの commonService.ts コードは全体ファイルの一部です。
以下の HeaderStore、headersProvider、sessionAuth コードは、互いに独立したファイルの例ではなく、プロジェクト共通 HTTP アダプター (rxjsHttpService.ts/commonService.ts) の各部分を分けて説明するものです。全体ファイル構造を最初に見たい場合は、HTTP クライアントの最小完成形/拡張形全体コードを確認した後にこのページを読んでください。
ブラウザで共有するヘッダー
ログイン後に受け取ったアクセストークンのように複数のサービスが一緒に使用する必要があるヘッダーはHeaderStoreに保管できます。
commonService.ts
tsimport { createHeaderStore } from "@byeolnaerim/typed-rx-http";
export const headerStore = createHeaderStore({
"Content-Type": "application/json",
});
headerStore.merge({
Authorization: `Bearer ${accessToken}`,
});
headerStore.remove("Authorization");Next.jsではブラウザとサーバーヘッダーを分ける
クライアントコンポーネントではHeaderStoreを読み取り、サーバーコンポーネントではクッキーを読み取るように headersProviderを作成できます。この関数ではCSRとSSRのヘッダー取得方法を一箇所で分離できます。
commonService.ts
tsconst headersProvider = async () => {
if (typeof window !== "undefined") {
return headerStore.get();
}
const { cookies } = await import("next/headers");
const accessToken = (await cookies()).get("accessToken")?.value;
return accessToken
? { Authorization: `Bearer ${accessToken}` }
: {};
};
export const service = createHttpClient<paths>({
baseUrl: process.env.NEXT_PUBLIC_API_URL || "",
headerStore,
headersProvider,
});401リフレッシュが必要な場合はcallApiで一度ラップする
自動生成サービスを一つずつ修正せずに、共通callApiにセッションオペレーターを付けます。これによりすべての生成サービスが同じトークン取得とリフレッシュルールを使用します。
commonService.ts
tsimport { createSessionAuth } from "@byeolnaerim/typed-rx-http";
import { defer } from "rxjs";
const sessionAuth = createSessionAuth({
headerStore,
tokenUrl: "/api/auth/token",
refreshUrl: "/api/auth/token/refresh",
logoutUrl: "/api/auth/logout",
onLoginChange: (loggedIn) => setLogin(loggedIn),
});
export const callApi = (serviceArguments) =>
defer(() => service.callApi(serviceArguments)).pipe(
sessionAuth.withSessionAuth(),
);Authorizationがない場合はトークンエンドポイントを最初に確認し、元のリクエストが401の場合はリフレッシュ後にもう一度リクエストします。リフレッシュも失敗した場合はログアウトエンドポイントを呼び出し元のエラーを伝えます。
refresh/retry なしでトークン同期だけが必要な場合
401 refresh/retry を使用せず、リクエスト前にトークンだけを同期するには withEnsureToken() を使用します。
return client.callApi(...).pipe(
auth.withEnsureToken(),
);認証が必要ない場合は
export const { callApi, callApiStream } = createHttpClient<paths>({
baseUrl: "/api",
});公開APIや簡単なプロジェクトではこれで十分です。HeaderStoreとセッション認証は必須構造ではありません。