Middleware & Sessions
Middleware: ประตูหน้าทุก request
หัวข้อที่มีชื่อว่า “Middleware: ประตูหน้าทุก request”Middleware คือ function ตัวเดียวที่รัน ก่อนทุก request ถูกจัดการ ตัว middleware อยู่ใน src/middleware.ts และ export onRequest(context, next) — คุณทำงาน แล้วเรียก next() เพื่อไปต่อยัง page หรือ endpoint (หรือ short-circuit ด้วย Response ของตัวเอง)
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, next) => { // Runs for every request, before the route. const token = context.cookies.get('session')?.value; context.locals.user = token ? await getUser(token) : null; // share data downstream
// Guard a section of the site. if (context.url.pathname.startsWith('/admin') && !context.locals.user) { return context.redirect('/login'); // short-circuit — never reach the page }
return next(); // continue to the route});sequenceDiagram
participant B as Browser
participant M as onRequest middleware
participant R as Route (page/endpoint)
B->>M: request
M->>M: read cookies, set context.locals
alt not authorized
M-->>B: redirect / 403 (short-circuit)
else authorized
M->>R: next()
R-->>B: rendered response
end context.locals: data ที่ share ต่อ request
หัวข้อที่มีชื่อว่า “context.locals: data ที่ share ต่อ request”หัวใจของ middleware คือ context.locals — object ที่อยู่ตลอดหนึ่ง request อะไรก็ตามที่คุณ set ไว้ (user ปัจจุบัน, request id, feature flag) อ่านได้ในทุก page, endpoint และ action ของ request นั้นผ่าน Astro.locals / context.locals ของ action นี่คือวิธีที่ middleware ส่ง data ที่คำนวณแล้วให้ส่วนที่เหลือของ request โดยไม่ใช้ global state
---// In any on-demand page — read what middleware put there.const user = Astro.locals.user;---{user ? <p>Hi, {user.name}</p> : <a href="/login">Sign in</a>}Sessions: state ต่อ user ข้าม request
หัวข้อที่มีชื่อว่า “Sessions: state ต่อ user ข้าม request”context.locals อยู่แค่หนึ่ง request การจะจำ user ข้าม request — shopping cart, การ login — คุณใช้ sessions ระบบ session ของ Astro เก็บ data ฝั่ง server โดย key ด้วย cookie backed ด้วย driver ที่ config ไว้ (memory ตอน dev, KV/Redis/database ตอน production)
---// Read/write session data in a component script:const cart = (await Astro.session?.get('cart')) ?? [];---<p>{cart.length} items in your cart</p>// In an action handler, context.session is the same session:handler: async (input, context) => { const cart = (await context.session?.get('cart')) ?? []; cart.push(input.productId); await context.session?.set('cart', cart); return cart;}session เปิดให้ใช้ get, set และ destroy ตอน logout คุณล้างทุกอย่างด้วย Astro.session?.destroy() ซึ่งลบ session cookie และ data ฝั่ง server ต่างจาก cookie ที่คุณ set เอง session data อยู่บน server — cookie เก็บแค่ id ที่ opaque — จึงปลอดภัยสำหรับ state ที่ sensitive
pattern ของ auth
หัวข้อที่มีชื่อว่า “pattern ของ auth”สามชิ้นนี้ประกอบกันเป็น auth flow มาตรฐาน: middleware อ่าน session cookie แล้ววาง user บน context.locals; pages อ่าน Astro.locals.user เพื่อ render UI แบบ signed-in vs signed-out; และ guard ใน middleware redirect request ที่ยังไม่ auth ออกจาก protected route การ login เขียน session การ logout เรียก destroy()