브라우저가 크로스 오리진 요청 전에 보내는 CORS 프리플라이트(OPTIONS)를 curl로 재현해, 서버 CORS 설정을 검증하는 레시피입니다.
브라우저가 크로스 오리진 요청 전에 보내는 CORS 프리플라이트(OPTIONS)를 curl로 재현해, 서버 CORS 설정을 검증하는 레시피입니다.
# simulate the browser's preflight OPTIONS request:
curl -i -X OPTIONS https://api.example.com/users \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization'# a passing preflight echoes back the allowances:
# HTTP/1.1 204 No Content
# Access-Control-Allow-Origin: https://app.example.com
# Access-Control-Allow-Methods: POST, GET, OPTIONS
# Access-Control-Allow-Headers: Content-Type, Authorization
# Access-Control-Max-Age: 86400// This request is non-simple (custom header + JSON), so the browser
// automatically fires an OPTIONS preflight before the POST:
await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer <token>'
},
body: JSON.stringify({ name: 'Ada' })
});브라우저는 '단순 요청'이 아닌 경우(예: `Content-Type: application/json`, 커스텀 헤더, PUT/DELETE 등) 실제 요청 전에 OPTIONS 프리플라이트를 먼저 보냅니다. 이때 `Origin`, `Access-Control-Request-Method`, `Access-Control-Request-Headers`로 '이런 요청을 보내도 되냐'고 묻습니다. 위 curl은 이 프리플라이트를 그대로 흉내 냅니다.
서버가 응답에서 `Access-Control-Allow-Origin`(요청 Origin과 일치해야 함), `Access-Control-Allow-Methods`, `Access-Control-Allow-Headers`로 해당 메서드·헤더를 허용해야 실제 요청이 진행됩니다. 하나라도 빠지면 브라우저가 요청을 차단하며 콘솔에 CORS 에러가 뜹니다(응답 자체는 200이어도 JS가 못 읽음).
쿠키·인증정보를 함께 보내려면 서버가 `Access-Control-Allow-Credentials: true`를 응답하고 `Access-Control-Allow-Origin`을 와일드카드 `*`가 아닌 구체적 출처로 지정해야 합니다. 프리플라이트 결과는 `Access-Control-Max-Age` 동안 캐시되어 반복 OPTIONS를 줄여 줍니다. CORS는 서버가 아닌 브라우저가 강제하는 규칙이라 curl·서버 간 직접 호출에는 적용되지 않는다는 점을 기억하세요.