Разруливаем CORS на 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;

...





К вопросу о том, зачем фронтендерам базовый девопс.