feat: 인프라 개선 — 헬스체크, 로깅, 보안, CI 검증
- /health + /ready 엔드포인트 추가 (DB/Redis 상태 확인) - RequestID 미들웨어 + 구조화 JSON 로깅 - 체인 트랜잭션 per-user rate limit (20 req/min) - DB 커넥션 풀 설정 (MaxOpen 25, MaxIdle 10, MaxLifetime 5m) - Graceful Shutdown 시 Redis/MySQL 연결 정리 - Dockerfile HEALTHCHECK 추가 - CI에 go vet + 빌드 검증 단계 추가 (deploy 전 실행) - 보스 레이드 클라이언트 입장 API (JWT 인증) - Player 프로필 모듈 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -76,7 +76,7 @@ func ServerAuth(c *fiber.Ctx) error {
|
||||
key := c.Get("X-API-Key")
|
||||
expected := config.C.InternalAPIKey
|
||||
if key == "" || expected == "" || subtle.ConstantTimeCompare([]byte(key), []byte(expected)) != 1 {
|
||||
log.Printf("ServerAuth 실패: IP=%s, Path=%s, KeyPresent=%v", c.IP(), c.Path(), key != "")
|
||||
log.Printf("ServerAuth 실패: IP=%s, Path=%s", c.IP(), c.Path())
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "유효하지 않은 API 키입니다"})
|
||||
}
|
||||
return c.Next()
|
||||
|
||||
@@ -26,6 +26,9 @@ func Idempotency(c *fiber.Ctx) error {
|
||||
if key == "" {
|
||||
return c.Next()
|
||||
}
|
||||
if len(key) > 256 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Idempotency-Key가 너무 깁니다"})
|
||||
}
|
||||
|
||||
// userID가 있으면 키에 포함하여 사용자 간 캐시 충돌 방지
|
||||
redisKey := "idempotency:"
|
||||
|
||||
17
pkg/middleware/requestid.go
Normal file
17
pkg/middleware/requestid.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// RequestID generates a unique request ID for each request and stores it in Locals and response header.
|
||||
func RequestID(c *fiber.Ctx) error {
|
||||
id := c.Get("X-Request-ID")
|
||||
if id == "" {
|
||||
id = uuid.NewString()
|
||||
}
|
||||
c.Locals("requestID", id)
|
||||
c.Set("X-Request-ID", id)
|
||||
return c.Next()
|
||||
}
|
||||
@@ -9,5 +9,6 @@ func SecurityHeaders(c *fiber.Ctx) error {
|
||||
c.Set("X-XSS-Protection", "0")
|
||||
c.Set("Referrer-Policy", "strict-origin-when-cross-origin")
|
||||
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'")
|
||||
c.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user