ข้ามไปยังเนื้อหา

Middleware & Sessions

Middleware คือ function ตัวเดียวที่รัน ก่อนทุก request ถูกจัดการ ตัว middleware อยู่ใน src/middleware.ts และ export onRequest(context, next) — คุณทำงาน แล้วเรียก next() เพื่อไปต่อยัง page หรือ endpoint (หรือ short-circuit ด้วย Response ของตัวเอง)

src/middleware.ts
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
middleware รันก่อน route และ short-circuit ได้

หัวใจของ 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>}

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

สามชิ้นนี้ประกอบกันเป็น 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()

`onRequest` middleware รันเมื่อไร?
`context.locals` มีไว้ทำอะไร?
session ต่างจาก `context.locals` อย่างไร?
คุณล้าง session ของ user ตอน logout อย่างไร?