因业务调整,需要在gateway中添加websocket的转发地址(PS:网上目前没有关于这个错误解决),原来的配置如下

代码可见,我在cors‐configurations配置了跨域信息,拦截所有请求,下面配置了websocket的路由规则。

代码如下

spring:
  application:
    name: api-gateway-server
  cloud:
    # 网关配置
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        cors‐configurations:
          '[/**]': # 匹配请求
            # allowedOrigins: "*"
            allowedOriginPatterns: '*' #跨域处理 允许所有的域
            allowCredentials: true # 是否允许携带cookie
            allowedMethods: # 支持的方法
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
      # 路由配置
      routes: # 集合
        - id: websocket-reader-connect
          uri: lb://library-system-reader
          order: 2
          predicates:
            - Path=/librarySystemReader/websocket端点/info/**
          filters:
            - StripPrefix= 1
        - id: websocket-reader
          uri: lb:ws://library-system-reader
          order: 3
          predicates:
            - Path=/librarySystemReader/websocket端点/**
          filters:
            - StripPrefix= 1

 前端报跨域问题,检查发现我在gateway和项目websocket中都配置了AllowedOriginPattern,导致出现了两个Access-Control-Allow-Origin响应头。websocket原配置如下

代码贴上

    //webSocket配置类
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注册端点
        registry.addEndpoint("/librarySystemReader-websocket").setAllowedOriginPatterns("*").addInterceptors(new HttpHandShakeInterceptor()).withSockJS();
    }

我将websocket配置中的setAllowedOriginPattern删除,本以为会连接成功,重启之后Stomp的get info显示403(Forbidden)。

不是最终解决办法

方法一:查问题最后发现如果想使用websocket,gateway不能配置跨域,原因不太清楚,第一种办法只能将gateway中的跨域注释掉,测试连接成功。

 

10月26日解决问题

方法二:和一些大佬交流之后,想到一个办法:

在gateway中设置过滤器检测websocket地址,删除gateway配置的跨域信息,使用websocket的跨域配置,在gateway中配置过滤器,设置此过滤器优先级最低。拦截websocket的请求将gateway配置的跨域头移除。

websocket、gateway采用之前的配置。

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class WebsocketFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().pathWithinApplication().toString();
        substring = path.substring(0, path.indexOf("/", path.indexOf("/", 2) + 1));
        //检测websocket请求
        if(substring.equals("/librarySystemReader/librarySystemReader-websocket")){
            if(CorsUtils.isCorsRequest(request)){
                //删除头信息
                ServerHttpResponse response = exchange.getResponse();
                response.getHeaders().remove("Access-Control-Allow-Origin");
                response.getHeaders().remove("Access-Control-Allow-Credentials");
            }
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        //注意我将优先级设置最低
        return 4;
    }
}

测试结果连接成功!

下面是简单解释了一下websocket和http区别

1、WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。

2、WebSocket是需要浏览器和服务器握手进行建立连接的。而http是浏览器发起向服务器的连接,服务器预先并不知道这个连接。

联系

3、WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐