Middleware
เปรียบเทียบโมเดล middleware
หัวข้อที่มีชื่อว่า “เปรียบเทียบโมเดล middleware”Express middleware คือ (req, res, next) => void เรียก next() เพื่อส่งต่อ หรือเรียก res.json() เพื่อจบ request เลย ส่วน Echo ใช้แนวคิด pipeline เดียวกันแต่อาศัย error-return pattern และ closure ของ Go:
// Middleware signature ของ Echofunc(next echo.HandlerFunc) echo.HandlerFuncMiddleware คืน HandlerFunc ใหม่ที่ wrap next ไว้ เรียก next(c) เพื่อส่งต่อ หรือคืน error เพื่อยกเลิก
// Express middlewarefunction requestLogger(req, res, next) { console.log(`${req.method} ${req.path}`); next();}app.use(requestLogger);// Echo middlewarefunc RequestLogger(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { fmt.Printf("%s %s\n", c.Request().Method, c.Request().URL.Path) return next(c) // ส่งต่อ }}
e.Use(RequestLogger)Built-in middleware
หัวข้อที่มีชื่อว่า “Built-in middleware”Echo มี middleware พร้อมใช้งานใน production หลายตัวใน sub-package middleware
// Express — ต้องการ package ภายนอกimport morgan from 'morgan';import cors from 'cors';
app.use(morgan('combined'));app.use(cors({ origin: '*' }));// ไม่มี recover built-in — ต้องใช้ express-async-errors หรืออื่น ๆ// Echo built-in — ไม่ต้องการ package เพิ่มimport "github.com/labstack/echo/v4/middleware"
e.Use(middleware.Logger()) // log request แบบ structured ไปยัง stdoute.Use(middleware.Recover()) // จับ panic คืน 500e.Use(middleware.CORS()) // default: อนุญาตทุก origin
// จำกัด CORS เฉพาะ origin ที่ระบุ:e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{"https://example.com"}, AllowMethods: []string{http.MethodGet, http.MethodPost},}))ลำดับ middleware
หัวข้อที่มีชื่อว่า “ลำดับ middleware”เหมือน Express ลำดับมีความสำคัญ middleware ที่ลงทะเบียนก่อนจะทำงานก่อน Logger และ Recover ควรอยู่ชั้นนอกสุดเสมอ
e.Use(middleware.Logger()) // 1 — log ทุก requeste.Use(middleware.Recover()) // 2 — จับ panic จาก handler ที่ตามมาe.Use(authMiddleware) // 3 — ตรวจสอบ auth หลังจาก logging ตั้งค่าแล้วMiddleware ระดับ route และ group
หัวข้อที่มีชื่อว่า “Middleware ระดับ route และ group”ใน Express คุณส่ง middleware เข้าไปที่ route ได้ตรง ๆ ส่วน Echo ทำแบบเดียวกันได้ด้วย .Use บน group
// Express — per-route middlewareapp.get('/admin', authMiddleware, adminHandler);
// Express — router-levelconst adminRouter = express.Router();adminRouter.use(authMiddleware);adminRouter.get('/', adminHandler);app.use('/admin', adminRouter);// Echo — per-route middlewaree.GET("/admin", adminHandler, authMiddleware)
// Echo — group-level middlewareadmin := e.Group("/admin")admin.Use(authMiddleware)admin.GET("", adminHandler)admin.GET("/users", adminUsersHandler)เขียน auth middleware เอง
หัวข้อที่มีชื่อว่า “เขียน auth middleware เอง”// Express JWT-like auth middlewarefunction requireAuth(req, res, next) { const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).json({ message: 'unauthorized' }); try { req.user = verifyToken(token); next(); } catch { res.status(401).json({ message: 'invalid token' }); }}// Echo custom auth middlewarefunc RequireAuth(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { header := c.Request().Header.Get("Authorization") if header == "" { return echo.NewHTTPError(http.StatusUnauthorized, "missing token") } parts := strings.SplitN(header, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { return echo.NewHTTPError(http.StatusUnauthorized, "bad token format") } claims, err := verifyToken(parts[1]) if err != nil { return echo.NewHTTPError(http.StatusUnauthorized, "invalid token") } // เก็บ claims ใน context สำหรับ handler ที่ตามมา c.Set("user", claims) return next(c) }}รันบนเครื่องของคุณ — ต้องการ Echo module และ network port