Независимый от языка способ избавиться от кошмара CORS и попутно изучить nginx!
Вчера мне приснился кошмар. Я пытался исправить высокоприоритетную ошибку во внешнем интерфейсе. Я быстро смог это исправить. Я был очень доволен собой. Я просто хотел быстро подключить интерфейс к серверу разработки и проверить, что он исправлен. Мое приложение работало в localhost:8080
, а сервер разработки в каком-то 10.10.1.123:80
(Эй вы, хакеры, не запускайте что-то подозрительное, как только увидите какой-то IP, который я придумал!). Я все запустил и не могу дождаться, чтобы увидеть, как это работает. Но затем я вижу знаменитое сообщение о проблеме CORS.
Доступ к XMLHttpRequest по адресу https://10.10.1.123/somepath» из источника https://localhost:8080 заблокирован политикой CORS: Ответ на предварительный запрос не проходит проверку контроля доступа: Нет Заголовок Access-Control-Allow-Origin присутствует в запрошенном ресурсе.
Я так разозлился, что проснулся! Существует еще один сценарий, в котором вы запускаете свой сервер локально на порту 8090
и пытаетесь использовать его локально на порту внешнего интерфейса 8080
. У тебя будет тот же кошмар. Я думаю, что почти все разработчики в какой-то момент своей карьеры столкнулись с этой невероятно раздражающей проблемой. Я здесь с постоянным исправлением, не полагаясь на какой-либо конкретный язык.
Шаг 1: Установка nginx
Для пользователей Mac
brew install nginx
Вот несколько полезных команд
brew services start nginx brew services status nginx brew services stop nginx brew services restart nginx
Для пользователей убунту
sudo apt-get install nginx
Некоторые полезные команды
sudo systemctl start nginx sudo systemctl status nginx sudo systemctl stop nginx sudo systemctl restart nginx
Для тех пользователей Windows, которые не используют wsl2 или других пользователей дистрибутива Linux, я верю в вас, вы можете выполнить поиск в Google и установить его самостоятельно 💪
Шаг 2: Конфигурация
На Mac конфигурация находится в:/usr/local/etc/nginx/nginx.conf
на убунту это
/etc/nginx/nginx.conf
Теперь замените серверную часть конфига на следующую
server { listen 9090; server_name localhost; #This is the main application (UI) location / { root html; proxy_pass https://localhost:8080/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Cookie $http_cookie; proxy_pass_request_headers on; } #This is the recipes microservice backend application in your local machine. replace the proxy pass with your application url location /recipes { proxy_pass https://localhost:8090/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Cookie $http_cookie; proxy_pass_request_headers on; } #This is the authentication backend application but in your dev machine. replace the proxy pass with your application url location /auth { proxy_pass https://10.13.1.213:8081/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Cookie $http_cookie; proxy_pass_request_headers on; } }
Вы должны заменить прокси-проход своим URL-адресом и путем к местоположению в соответствии с вашим префиксом внутреннего API. Теперь базовый URL-адрес, по которому вы будете получать доступ к своему внешнему приложению, будет https://localhost:9090
.
В интерфейсе приложения измените URL-адрес API следующим образом:
https://localhost:8090/auth
следует заменить на https://localhost:9090/auth
https://localhost:8090/recipe
следует заменить на https://localhost:9090/recipe
Позвольте мне объяснить конфигурацию на примерах.
Nginx будет работать на порту 9090. когда вы нажмете https://localhost:9090/recipes
, он перенаправит любой запрос с этим префиксом рецепта на https://localhost:8090/recipes
. Это будут примеры перенаправления:
https://localhost:9090/recipes/getAllRecices
→ https://localhost:8090/recipes/getAllRecipes
https://localhost:9090/recipes/delete/id
→ https://localhost:8090/recipes/delete/id
https://localhost:9090/auth/login
→
https://10.13.1.213:8081/auth/login
https://localhost:9090/auth/register
→ https://10.13.1.213:8081/auth/register
Он перенаправит запрос на все файлы cookie и другие полезные вещи.
Почему это работает? Поскольку теперь все ваше приложение находится под одним и тем же доменным именем, localhost:9090.
Так что все проблемы с CORS исчезнут!!
Ограничение
Как видите, у вас должен быть префикс пути, одинаковый для всех ваших API. В противном случае вам придется писать новую конфигурацию сервера для каждого URL-адреса. Учимся на примере:
Все наши запросы совпадают с auth
и перенаправляются на серверную часть. это работает, потому что у нас есть префикс auth
в бэкенде аутентификации для каждого API. Что произойдет, если вы спроектируете свой API таким образом без префикса? (Конечно, плохой дизайн)https://10.13.1.213:8081/login
https://10.13.1.213:8081/register
Эта маршрутизация не будет работать. Потому что он перенаправит запрос на https://10.13.1.213:8081/auth/login
, которого не существует.
Хакерский способ обойти это:
location /register { proxy_pass https://10.13.1.213:8081/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Cookie $http_cookie; proxy_pass_request_headers on; } location /login { proxy_pass https://10.13.1.213:8081/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Cookie $http_cookie; proxy_pass_request_headers on; }
Но это слишком много работы, верно?
Надеюсь, вы много узнали о CORS и nginx. Поначалу это может показаться немного трудоемким, но вы настраиваете nginx только один раз на своем компьютере, и вам никогда не придется искать исправление CORS для конкретного языка. Если вы разберетесь с этим достаточно хорошо, вы сможете обойти любую проблему CORS даже в продакшене, а также теперь вы довольно много знаете о nginx 😉
Некоторые другие мои арты
https://levelup.gitconnected.com/why-every-software-engineer-should-use-vim-b9fb97e69d97