English: Middleware
Zenqo는 표준 Go 미들웨어를 사용합니다: func(http.Handler) http.Handler
| 미들웨어 | 설명 |
|---|---|
middleware.Logger |
상태 코드, 지연 시간, IP를 포함한 구조화된 요청/응답 로깅 |
middleware.RequestID |
X-Request-Id 주입 (기존 헤더 검증 또는 새로 생성) |
middleware.RealIPWithConfig() |
신뢰할 수 있는 프록시의 헤더에서 r.RemoteAddr 설정 |
middleware.CORS() |
설정 가능한 CORS 헤더 |
middleware.SecureHeaders() |
보안 헤더: CSP, HSTS, X-Frame-Options 등 |
middleware.RateLimit() |
슬라이딩 윈도우 IP당 요청 횟수 제한 |
middleware.CSRF() |
이중 제출 쿠키 방식 CSRF 보호 |
Logger, RequestID, RealIP (사설 네트워크 CIDR), 패닉 복구는 core.NewApp() 사용 시 자동으로 등록됩니다.
// 전역
app.Use(middleware.CORS())
app.Use(middleware.SecureHeaders())
// 컨트롤러 수준
c.UseControllerMiddleware(middleware.RateLimit())
// 라우트 수준
c.GET("/upload", c.upload).Use(myMiddleware)app.Use(middleware.CORS(middleware.CORSConfig{
AllowOrigins: []string{"https://example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Authorization", "Content-Type"},
MaxAge: 86400,
}))인자 없이 호출하면 관대한 기본값(모든 오리진, 일반 메서드)이 적용됩니다. 부분 설정은 기본값과 병합됩니다 — 필요한 것만 오버라이드하세요.
기본적으로 NewApp()은 사설 네트워크 CIDR의 프록시 헤더만 신뢰합니다. 커스터마이즈:
app.Use(middleware.RealIPWithConfig(middleware.RealIPConfig{
TrustedProxies: []string{"10.0.0.0/8", "172.16.0.0/12"},
}))app.Use(middleware.RateLimit()) // IP당 분당 100회
app.Use(middleware.RateLimit(middleware.RateLimitConfig{
Max: 50,
Window: 30 * time.Second,
KeyFunc: func(r *http.Request) string {
return r.Header.Get("X-API-Key") // API 키 기준으로 제한
},
OnLimit: func(w http.ResponseWriter, r *http.Request) {
core.Error(w, 429, "요청이 너무 많습니다")
},
}))rl := middleware.NewRateLimiter(middleware.RateLimitConfig{
Max: 100,
Window: time.Minute,
})
app.Use(rl.Middleware())
defer rl.Stop() // 백그라운드 정리 고루틴 종료모든 요청에 설정되는 응답 헤더:
X-RateLimit-Limit— 윈도우당 최대 요청 수X-RateLimit-Remaining— 남은 요청 수X-RateLimit-Reset— 윈도우 리셋 Unix 타임스탬프Retry-After— 리셋까지 남은 초 (한도 초과 시에만)
app.UseStatic("/", "./public")
// ./public/index.html을 /에서 서빙
// 전역 접두사 자동 적용X-Request-Id가 모든 요청에 주입됩니다. 핸들러에서 조회:
id := middleware.GetRequestID(r.Context())클라이언트가 X-Request-Id 헤더를 보내면 안전한 문자 허용 목록에 검증 후 그대로 사용합니다. 없으면 새 ID를 생성합니다.