A. 요청 메소드 OPTIONS에 대한 설정을 추가하면 된다.
CORS 관련 확인을 위해서 사전요청preflight이 발생한다. 이 사전요청은 OPTIONS 요청 메소드로 이루어진다. 그래서 NGINX에서 OPTIONS 요청 메소드 처리를 추가하면 된다.
server {
...
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Cookie';
return 204;
}
...
}
}
Access-Control-Allow-Methods
Access-Control-Allow-Methods 다음 '' 안에는 허용을 원하는 메소드를 모두 적는다. PUT도 허용이 필요하면 아래처럼 PUT도 추가로 적으면 된다.
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
Access-Control-Allow-Credentials
이 부분을 true로 설정해야 세션 인증이 가능하다.
실제 자바스크립트 코드 예에서 httpRequest.withCredentials = true; 부분이 관련 코드다.
const httpRequest = new XMLHttpRequest();
const data = "{ }";
httpRequest.onreadystatechange = logContents;
httpRequest.withCredentials = true;
httpRequest.open('POST', 'https://api.taptorestart.com/v1/test/');
httpRequest.setRequestHeader('Cookie', 'sessionid=yoursessionid;');
httpRequest.setRequestHeader('Content-Type', 'application/json');
httpRequest.send(data);
Access-Control-Allow-Headers
Access-Control-Allow-Headers 다음에는 Content-Type, Authorization, Cookie 3가지를 추가했는데 상황에 따라 뺄 수도 있다.
CORS 상황에서 Content-Type을 안 넣게 되면 application/json 데이터는 전송이 안 된다. Authorization을 안 넣게 되면 Authorization 헤더에 담아 보내는 token 전송에 실패하게 된다. JWT 토큰 등 토큰을 사용한다면 추가하자. Cookie를 안 넣게 되면 Cookie 전송이 안 된다. 당연히 쿠키에 실어 보내는 세션 정보에 접근이 안 되어서 사용자 정보를 얻는데 실패하게 된다.
보통 3가지 경우가 모두 필요한 경우가 많으니 3가지 모두 추가하자.
return
return 204는 응답 상태코드 설정이다.
HTTP 상태 코드 중 204 코드는 No Content 코드다. 응답에 아무 것도 없는 경우다. 보안상 이유로 OPTIONS 메소드 요청의 경우 보통 응답을 포함시키지 않는다.
장고에서 많이 사용하는 django-cors-headers 팩키지 경우 허용된 호스트와 비허용된 호스트 관계 없이 상태 코드는 200, 응답은 없이 처리한다.
타 사이트의 경우 비허용된 호스트일 경우만 테스트 가능하다. 다른 응답 코드를 원한다면 직접 조사해보자. 트위터의 경우 상태 코드는 200, 콘텐츠는 없다.
google.com의 경우에는 상태 코드 405다.
관련 글
Q. CORS(Cross-Origin Resource Sharing)이란?
Q. CORS(Cross-Origin Resource Sharing) 사전요청preflight을 하지 않는 경우는?