Trigger a CORS preflight

브라우저가 크로스 오리진 요청 전에 보내는 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·서버 간 직접 호출에는 적용되지 않는다는 점을 기억하세요.

관련 헤더

관련 상태코드