diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-12-30 22:08:47 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-12-30 22:08:47 +0900 |
| commit | c2eb7513834eeb5adfa53fff897f585de87e4821 (patch) | |
| tree | 9e914051ca67e2f9e1fa301119bdec398ec9e55f /src/server/middleware/cors.ts | |
| parent | b839cae49efd4b9d35c2868a4137101a4d71bd7f (diff) | |
| download | kioku-c2eb7513834eeb5adfa53fff897f585de87e4821.tar.gz kioku-c2eb7513834eeb5adfa53fff897f585de87e4821.tar.zst kioku-c2eb7513834eeb5adfa53fff897f585de87e4821.zip | |
feat(security): add rate limiting and CORS middleware
- Add rate limiting to login endpoint (5 requests/minute per IP)
- Configure CORS middleware with environment-based origin control
- Expose rate limit headers in CORS for client visibility
- Update hono to 4.11.3 for rate limiter peer dependency
🤖 Generated with [Claude Code](https://claude.ai/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/server/middleware/cors.ts')
| -rw-r--r-- | src/server/middleware/cors.ts | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/server/middleware/cors.ts b/src/server/middleware/cors.ts new file mode 100644 index 0000000..ce097ac --- /dev/null +++ b/src/server/middleware/cors.ts @@ -0,0 +1,42 @@ +import { cors } from "hono/cors"; + +/** + * CORS middleware configuration. + * Uses CORS_ORIGIN environment variable to configure allowed origins. + * If not set, defaults to same-origin only (no CORS headers). + * + * Examples: + * - CORS_ORIGIN=https://kioku.example.com (single origin) + * - CORS_ORIGIN=https://example.com,https://app.example.com (multiple origins) + */ +function getAllowedOrigins(): string[] { + const origins = process.env.CORS_ORIGIN; + if (!origins) { + return []; + } + return origins.split(",").map((o) => o.trim()); +} + +export function createCorsMiddleware() { + const allowedOrigins = getAllowedOrigins(); + + // If no origins configured, don't add CORS headers + if (allowedOrigins.length === 0) { + return cors({ + origin: () => "", + }); + } + + return cors({ + origin: allowedOrigins, + allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allowHeaders: ["Content-Type", "Authorization"], + exposeHeaders: [ + "RateLimit-Limit", + "RateLimit-Remaining", + "RateLimit-Reset", + ], + maxAge: 86400, // 24 hours + credentials: true, + }); +} |
