Независимый от языка способ избавиться от кошмара 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/getAllReciceshttps://localhost:8090/recipes/getAllRecipes

https://localhost:9090/recipes/delete/idhttps://localhost:8090/recipes/delete/id

https://localhost:9090/auth/login
https://10.13.1.213:8081/auth/login

https://localhost:9090/auth/registerhttps://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

https://levelup.gitconnected.com/beginner-guide-to-started-with-vim-without-blowing-your-head-off-30313088a9f3