API Features
CORS, rate limiting, and health checks
CORS
Auto-Behavior
| Mode | Default |
|---|---|
| Development | Permissive (all origins allowed) |
| Production | Disabled (no CORS headers) |
Manual Configuration
CORS is configured under the server section:
// arcway.config.js
export default {
server: {
cors: {
origin: ['https://app.example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400,
},
// Or: cors: true (permissive), cors: false (disabled)
},
};OPTIONS preflight requests are handled automatically.
Per-Route CORS
Use corsMiddleware from arcway/middlewares for per-prefix CORS settings:
// api/external/_middleware.js
import { corsMiddleware } from 'arcway/middlewares';
export default {
handler: corsMiddleware({
origin: ['https://partner.example.com'],
credentials: true,
}),
};Rate Limiting
Available as middleware. Import createRateLimitMiddleware and a store from arcway:
// api/_middleware.js
import { createRateLimitMiddleware, MemoryRateLimitStore } from 'arcway';
const store = new MemoryRateLimitStore();
export default {
handler: createRateLimitMiddleware(
{
max: 100, // Max requests per window
windowMs: 60_000, // Window size (1 minute)
keyFn: (req) => req.headers['x-forwarded-for'] || req.ip || 'unknown',
},
store,
),
};The keyFn receives ctx.req (the same request object available in handlers), so you can use any request property — req.ip, req.headers, req.session, etc. — to compute a rate-limit key.
MemoryRateLimitStore is for single-process deployments. For distributed/multi-replica deployments, use RedisRateLimitStore:
// api/_middleware.js
import { createRateLimitMiddleware, RedisRateLimitStore } from 'arcway';
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
const store = new RedisRateLimitStore(redis);
export default {
handler: createRateLimitMiddleware(
{
max: 100,
windowMs: 60_000,
},
store,
),
};Returns 429 Too Many Requests with Retry-After and X-RateLimit-* headers when limit is exceeded.
Health Checks
GET /_system/health is automatically available.
Response (healthy):
{
"status": "ok",
"components": {
"database": { "status": "ok", "responseMs": 3 },
"redis_queue": { "status": "ok", "responseMs": 1 }
}
}Response (degraded): Returns 503 with component-level status.