Spring Cloud Gateway如何返回WebSocket目标路由的握手响应头
Spring Cloud Gateway如何返回WebSocket目标路由的握手响应头
嘿,我之前也碰到过一模一样的问题!Spring Cloud Gateway默认在WebSocket握手环节,不会自动把后端服务器返回的自定义响应头转发给客户端,得我们手动加个过滤器来处理才行。下面给你一步步讲怎么解决:
原因分析
Spring Cloud Gateway的默认逻辑里,WebSocket握手的响应头不会被自动透传——网关主要关注路由转发,对于握手阶段的响应头没有做默认的复制处理,所以需要我们自定义过滤器来拦截并转发这些头。
解决方案步骤
1. 自定义网关过滤器工厂
这个过滤器的作用就是在握手完成后,把后端服务器返回的响应头复制到网关给客户端的响应里。创建一个Java类:
import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class WebSocketHeaderForwardFilterFactory extends AbstractGatewayFilterFactory<WebSocketHeaderForwardFilterFactory.Config> { public WebSocketHeaderForwardFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { return chain.filter(exchange).then(Mono.fromRunnable(() -> { // 从网关上下文获取后端返回的响应头 HttpHeaders upstreamHeaders = exchange.getAttribute("org.springframework.cloud.gateway.support.ServerWebExchangeUtils.RESPONSE_HEADERS_ATTR"); if (upstreamHeaders != null) { // 把后端所有响应头复制到网关响应中 exchange.getResponse().getHeaders().putAll(upstreamHeaders); // 如果你只需要转发特定自定义头(比如以X-Custom-开头的),可以改成这个逻辑: // upstreamHeaders.forEach((key, value) -> { // if (key.startsWith("X-Custom-")) { // exchange.getResponse().getHeaders().add(key, value.get(0)); // } // }); } })); }; } // 可在这里定义过滤器配置参数,比如指定要转发的头列表 public static class Config { } }
2. 修改网关路由配置,添加过滤器
打开你的application.yaml,在对应的WebSocket路由里加上这个过滤器:
server: port: 8383 spring: cloud: gateway: routes: - id: websocket_route uri: ws://localhost:8080/ws predicates: - Path=/ws/** filters: - WebSocketHeaderForward
测试验证
重启Spring Cloud Gateway和后端WebSocket服务,用客户端连接网关的WebSocket地址。你可以通过浏览器开发者工具查看握手请求的响应头,或者用专门的WebSocket客户端工具,就能看到后端服务器添加的自定义头已经被网关转发回来了。
备注:内容来源于stack exchange,提问作者Daniel Naves
相关产品推荐
相关产品推荐

