Вопрос или проблема
Как настроить CORS для API-шлюза и сокетов в микросервисах Spring Boot
У меня есть приложение на Springboot Microservice. В моем приложении есть 4 микросервиса.
API-шлюз,
управление пользователями,
idm-сервис,
engine-service.
Я использую React в качестве фронтенда.
API-шлюз содержит конфигурацию, связанную с CORS, и я использую веб-сокет для моего engine-service, поэтому у него есть конфигурация веб-сокета.
Я сталкиваюсь с проблемой при коммуникации с сокетом engine-service.
Когда я пытаюсь установить соединение по сокету из React, сначала он идет в API-шлюз, поэтому мне нужно добавить необходимую конфигурацию CORS в API-шлюзе.
Конфигурация API-шлюза:
cors-configurations:
'[/**]':
allowCredentials: true
allowedOrigins:
- "http://localhost:3000"
allowedHeaders: "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTIONS
- PATCH
Я должен добавить allowCredentials: true
, чтобы разрешить соединение по веб-сокету, и это работает хорошо.
Конфигурация сокета engine-service:
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint(registryEndpoint).setAllowedOrigins("http://localhost:3000").withSockJS();
}
Теперь снова мне нужно добавить setAllowedOrigins
в конфигурацию веб-сокета. Когда запрос приходит в engine-service, я получаю ошибку следующего вида:
Заголовок 'Access-Control-Allow-Origin' содержит несколько значений 'http://localhost:3000, http://localhost:3000', но разрешено только одно.
Сейчас я не могу найти решение для этого. Все запросы должны проходить через API-шлюз, поэтому мне нужно добавить конфигурацию CORS там, иначе я получу ошибку CORS в API-шлюзе. Если я добавляю setAllowedOrigins
в API-шлюз, я получаю ошибку в engine-service.
Можете ли вы подсказать мне, как решить эту ошибку?
Для соединения по веб-сокету, мне следует напрямую взаимодействовать с engine-service, а не проходить через API-шлюз?
Ответ или решение
Конечно! Давайте рассмотрим проблему конфигурации CORS для API Gateway и WebSocket в ваших микросервисах Spring Boot и предложим решение.
Проблема
Вы имеете API Gateway, который выполняет роль прокси-сервера для ваших микросервисов. У вас есть множество CORS настроек и вы сталкиваетесь с проблемой дублирования заголовка Access-Control-Allow-Origin
, когда происходит настройка WebSocket соединения из интерфейса React, что приводит к ошибке.
Решение
Чтобы избежать конфликта заголовков и правильно настроить CORS для вашего API Gateway и микросервиса Engine, выполните следующие шаги:
1. Настройка CORS в API Gateway
Ваш API Gateway должен управлять всеми CORS запросами, включая запросы, связанные с WebSocket. Убедитесь, что ваша конфигурация CORS в API Gateway выглядит следующим образом:
cors-configurations:
'[/**]':
allowCredentials: true
allowedOrigins:
- "http://localhost:3000"
allowedHeaders: "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTIONS
- PATCH
Это уже правильно, но стоит убедиться, что эти настройки применяются ко всем маршрутам, включая маршруты WebSocket.
2. Удаление setAllowedOrigins из Engine Service
Вам не нужно добавлять setAllowedOrigins
в конфигурации WebSocket в вашем EngineService
. Вместо этого настройка CORS в вашем API Gateway будет обрабатывать CORS заголовки для начинающегося WebSocket соединения.
Вот как может выглядеть ваш код без setAllowedOrigins
:
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint(registryEndpoint).setAllowedOrigins("*").withSockJS();
}
Здесь присутствует setAllowedOrigins("*")
, но так как CORS уже обрабатывается на стороне API Gateway, может быть даже лучше убрать этот метод или оставить его с *
, чтобы гарантировать, что нет конфликтов.
3. Убедитесь в правильной настройке прокси сервера
Ваш API Gateway должен обрабатывать все запросы как CORS, включая запросы WebSocket. Убедитесь, что у вас правильно настроен маршрут в API Gateway для WebSocket:
@Override
public void configure(HttpSecurity http) throws Exception {
http.cors().and()
.authorizeRequests()
.antMatchers("/ws/**").permitAll() // разрешите доступ к WebSocket
.anyRequest().authenticated();
}
4. Проверьте настройки на стороне клиента
В вашем React приложении убедитесь, что вы корректно инициализируете подключение к WebSocket через API Gateway:
const socket = new SockJS('http://localhost:8080/ws'); // используйте URL вашего API Gateway
const stompClient = Stomp.over(socket);
stompClient.connect({}, (frame) => {
console.log('Connected: ' + frame);
});
Заключение
Эти шаги должны помочь вам настроить CORS между вашим API Gateway и микросервисом Engine, устранив ошибки, связанные с Access-Control-Allow-Origin
. Убедившись, что весь трафик WebSocket проходит через API Gateway, вы избежите конфликтов и дублирования заголовков CORS.
Если у вас возникнут дополнительные вопросы или потребуется дальнейшая помощь, не стесняйтесь спрашивать!