npm i cors
cors는 CORS(Cross-origin resource sharing)를 활성화하는데 사용하는 Connect/Express 미들웨어이다.
(Cross-origin resource sharing)
서로 다른 도메인 간 리소스 요청을 처리하는 메커니즘이다.
<img> 태그로 다른 도메인의 이미지 파일을 가져오거나 <link> 태그로 CSS를 가져오는 등의 요청은 기본적으로 다른 도메인 간에서도 가능하다.
하지만 스크립트 부분(<script> 태그)에서 생성된 ‘교차 도메인’ 요청(특히 Ajax 요청)은 same-origin security policy에 의해 기본적으로 금지된다.
CORS는 브라우저와 서버가 상호작용하여 교차 오리진 요청을 허용하는 것이 안전한지 결정하는 방법을 정의한다.
웹 콘텐츠의 출처(origin)는 접근할 때 사용하는 URL의 스킴(프로토콜, 호스트(도메인), 포트로 정의된다.
두 객체의 스킴, 호스트, 포트가 모두 일치하는 경우 같은 출처를 가졌다고 말한다.
일부 작업은 동일 출처 콘텐츠로 제한되나, CORS를 통해 제한을 해제할 수 있다.
웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행한다.
웹 브라우저에서 해당 정보를 읽는 것이 허용된 출처라는 것을 서버에 설명할 수 있는 새로운 HTTP 헤더를 추가함으로써 동작한다.
Access-Control-Allow-Origin: *
: 모든 클라이언트의 요청을 허용서버 데이터에 변경을 일으키는 요청인 Ajax 및 HTTP 요청 메서드(보통 GET 이외의 메서드 또는 특정 MIME 유형의 POST)의 경우
→ 브라우저가 요청을 “preflight”하여 OPTIONS 메서드로 서버에 요청을 보냄(이 도메인을 허용하니?)
→ 서버에서 승인하면, 실제 요청을 전송
서버는 인증 정보(쿠키 및 HTTP 인증 데이터 포함)를 요청과 함께 전송해야 하는지를 클라이언트에 알릴 수 있다.
[GET](https://developer.mozilla.org/ko/docs/Web/HTTP/Methods/GET)
[HEAD](https://developer.mozilla.org/ko/docs/Web/HTTP/Methods/HEAD)
[POST](https://developer.mozilla.org/ko/docs/Web/HTTP/Methods/POST)
[Connection](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Connection)
, User-Agent (en-US), Fetch 명세에서 “forbidden header name”으로 정의한 헤더)외에, 수동으로 설정할 수 있는 헤더는 오직 Fetch 명세에서 “CORS-safelisted request-header”로 정의한 헤더 뿐이다.[Accept](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Accept)
[Accept-Language](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Accept-Language)
[Content-Language](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Language)
[Content-Type](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Type)
(아래의 추가 요구 사항에 유의)[Content-Type](https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Content-Type)
헤더는 다음의 값들만 허용application/x-www-form-urlencoded
multipart/form-data
text/plain
XMLHttpRequestUpload
객체에는 이벤트 리스너가 등록되어 있지 않다. 이들은 [XMLHttpRequest.upload](https://developer.mozilla.org/ko/docs/Web/API/XMLHttpRequest/upload)
프로퍼티를 사용하여 접근한다.[ReadableStream](https://developer.mozilla.org/ko/docs/Web/API/ReadableStream)
객체가 사용되지 않는다.Access-Control-Allow-Origin 헤더를 추가해줘야 CORS 문제를 해결할 수 있다.
res.set 메서드로 직접 넣어도 되지만, 이를 대신 해주는 cors 모듈을 사용하면 편하다.
import cors from 'cors';
...
app.use(cors());
import cors from 'cors';
...
app.get('/경로', cors(), (req, res) => res.json({msg: 'CORS-enabled'}));
const corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
};
app.use(cors(corsOptions));
origin
옵션에 제공된 함수를 사용하여 오리진을 동적으로 인증할 수 있다.
callback(error, origin)
을 가진 콜백을 전달origin
인수는 미들웨어의 오리진 옵션에 허용된 모든 값이 가능(함수 제외)const corsOptions = {
origin: function (origin, callback) {
// db.loadOrigins is an example call to load
// a list of origins from a backing database
db.loadOrigins(function (error, origins) {
callback(error, origins)
})
}
};
특정 CORS 요청은 복잡한 것으로 여겨지며 초기 OPTIONS 요청(aka pre-flight request)이 필요하다.
복잡한 요청의 예
pre-flight를 활성화하려면 지원할 경로에 OPTIONS 핸들러를 추가해야 한다.
app.options('/지원할/경로', cors()); // enable pre-flight request for DELETE request
app.del('/지원할/경로', cors(), (req, res) => {
...
});
또는 모든 경로에 대해 활성화 가능
app.options('*', cors()); // include before other routes
NOTE: 이 미들웨어를 애플리케이션 수준 미들웨어(예: app.use(cors))로 사용할 때는 모든 경로에 대해 pre-flight 요청이 처리된다.
const allowlist = ['http://example1.com', 'http://example2.com'];
const corsOptionsDelegate = function (req, callback) {
const corsOptions;
if (allowlist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true }; // reflect (enable) the requested origin in the CORS response
} else {
corsOptions = { origin: false }; // disable CORS for this request
}
callback(null, corsOptions); // callback expects two parameters: error and options
};
const getOrigin = () => {
const origin = [process.env.URL_CLIENT, process.env.URL_ADMIN];
if (process.env.NODE_ENV === 'production') {
origin.push(process.env.URL_CLIENT_OLD);
}
return origin;
};
...
app.use(cors({ origin: getOrigin(), credentials: true }));
credentials? - 도메인 간 쿠키 공유
Access-Control-Allow-Credentials CORS 헤더를 구성한다.
Access-Control-Allow-Credentials
는 요청의 자격증명 모드([Request.credentials](https://developer.mozilla.org/ko/docs/Web/API/Request/credentials)
)가 "include
" 일때, 브라우저들이 응답을 프로트엔드 자바스트립트 코드에 노출할지에 대해 알려준다. 요청의 자격증명 모드가 "include
" 이고, Access-Control-Allow-Credentials
값이 true
일 경우에만 브라우저는 프로트엔드 자바스트립트에 응답을 노출한다. (자격증명 - 쿠키, authorization 헤더, TLS 클라이언트 인증서)헤더를 전달하려면 true
로 설정(아니면 헤더가 생략됨)