Headers & Session Auth
โปรเจกต์ที่ไม่ต้องการการรับรองตัวตนให้ใช้ createHttpClient เท่านั้น และแนบ HeaderStore และ session auth เฉพาะเมื่อจำเป็น
โค้ด commonService.ts ของหน้านี้เป็นส่วนหนึ่งของไฟล์ทั้งหมด
โค้ด HeaderStore, headersProvider, sessionAuth ด้านล่างนี้ไม่ได้เป็นตัวอย่างไฟล์ที่แยกกัน แต่เป็นการอธิบายแต่ละส่วนของ HTTP adapter ที่ใช้ร่วมกันในโปรเจกต์ (rxjsHttpService.ts/commonService.ts) หากต้องการดูโครงสร้างไฟล์ทั้งหมดก่อน ให้ตรวจสอบโค้ดทั้งหมดของ HTTP Client ที่สมบูรณ์แบบ/ขยายได้แล้วอ่านหน้านี้
header ที่จะแชร์ในเบราว์เซอร์
header ที่หลายบริการต้องใช้ร่วมกัน เช่น access token ที่ได้รับหลังจากล็อกอินสามารถเก็บไว้ที่HeaderStoreHeaderStore
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 จะแยก header ระหว่างเบราว์เซอร์และเซิร์ฟเวอร์
ใน Client Component จะอ่าน HeaderStore และใน Server Component จะอ่าน cookie headersProviderสามารถสร้างได้ ฟังก์ชันนี้จะแยกวิธีการดึง header ของ 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,
});หากต้องการ refresh 401 ให้ห่อด้วย callApi หนึ่งครั้ง
อย่าแก้ไขบริการที่สร้างขึ้นโดยอัตโนมัติทีละรายการ ให้แนบ session operator ไว้ในบริการสาธารณะcallApiจะทำให้บริการที่สร้างขึ้นทั้งหมดใช้กฎการค้นหาและ refresh โทเค็นเดียวกัน
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 ให้ตรวจสอบ token endpoint ก่อน และหากคำขอเดิมเป็น 401 ให้ร้องขออีกครั้งหลังจาก refresh หาก refresh ล้มเหลวให้เรียก logout endpoint และส่งต่อข้อผิดพลาดเดิม
ในกรณีที่ต้องการเพียงการซิงโครไนซ์ token โดยไม่ต้อง refresh/retry
หากไม่ใช้ 401 refresh/retry และต้องการเพียงซิงโครไนซ์ token ก่อนคำขอ ให้ใช้ withEnsureToken()
return client.callApi(...).pipe(
auth.withEnsureToken(),
);หากไม่ต้องการการรับรองตัวตน
export const { callApi, callApiStream } = createHttpClient<paths>({
baseUrl: "/api",
});สำหรับ API สาธารณะหรือโปรเจกต์ง่ายๆ นี่ก็เพียงพอแล้ว HeaderStore และ session auth ไม่ใช่โครงสร้างที่จำเป็น