Разруливаем CORS на NGINX
Как известно, в Node.js всё наоборот. Не приложение запускается внутри сервера, а сервер поднимается внутри приложения. И бывает, что нужно делать интересные приседания для казалось бы базовых вещей. Вот, например, CORS. Стандарт сам по себе вычурный — сначала браузер должен отправить preflight-запрос типа OPTIONS и получить в ответе заголовок
Плюс, заголовок может понадобиться, а может и не понадобиться для `GET`-запроса (зависит от того, посчитает ли его эвристика браузера достаточно «простым»). Критерии «простоты» достаточно мутные и гуляют от браузера к браузеру.
Итак, при разработке апишек мы приходим к необходимости интегрировать в наше приложение знание о спецификах CORS. Но зачем, у нас же есть Nginx, который прекрасно с этим справится, а заодно разгрузит наше приложение от «ненужных» OPTIONS-запросов.
Магия конфигов, например:
Таким образом, если наш допустимый источник запроса попал в регулярку, то мы запишем его имя в
Тут ещё может стать проблемой если в приложении подключена CORS-миддлвара и она тоже захочет сама прописать заголовки, когда до неё дойдёт какой-нибуть POST-запрос. Ну это тоже Nginx-умеет чистить
К вопросу о том, зачем фронтендерам базовый девопс.
Как известно, в Node.js всё наоборот. Не приложение запускается внутри сервера, а сервер поднимается внутри приложения. И бывает, что нужно делать интересные приседания для казалось бы базовых вещей. Вот, например, CORS. Стандарт сам по себе вычурный — сначала браузер должен отправить preflight-запрос типа OPTIONS и получить в ответе заголовок
Access-Control-Allow-Origin
, в котором будет сказано, что данные можно раздавать или всем (`*`) или конкретному ориджину (`mysite.com`) который мы установим вручную на сервере и отдадим в ответе. Вайлдкэрд тут недопустим (никаких *.mysite.com
, только a.mysite.com
).Плюс, заголовок может понадобиться, а может и не понадобиться для `GET`-запроса (зависит от того, посчитает ли его эвристика браузера достаточно «простым»). Критерии «простоты» достаточно мутные и гуляют от браузера к браузеру.
Итак, при разработке апишек мы приходим к необходимости интегрировать в наше приложение знание о спецификах CORS. Но зачем, у нас же есть Nginx, который прекрасно с этим справится, а заодно разгрузит наше приложение от «ненужных» OPTIONS-запросов.
Магия конфигов, например:
map $http_origin $cors_header {
default "";
"~^https://[^/]+\.mydomain\.com(:[0-9]+)?$" "$http_origin";
}
server {
add_header Access-Control-Allow-Headers "Content-Type" always;
add_header Access-Control-Allow-Origin $cors_header always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Max-Age: 86400;
if ($request_method = OPTIONS) {
return 200;
}
}
Таким образом, если наш допустимый источник запроса попал в регулярку, то мы запишем его имя в
Access-Control-Allow-Origin
. А если это был OPTIONS
запрос, то даже не будем отправлять его глубже в приложение, а сразу ответим браузеру статусом 200
и правильным заголовком.Тут ещё может стать проблемой если в приложении подключена CORS-миддлвара и она тоже захочет сама прописать заголовки, когда до неё дойдёт какой-нибуть POST-запрос. Ну это тоже Nginx-умеет чистить
proxy_hide_header Access-Control-Allow-Credentials;
proxy_hide_header Access-Control-Allow-Headers;
...
К вопросу о том, зачем фронтендерам базовый девопс.