websocket走Spring Cloud Gateway报错:java.lang.UnsupportedOperationException: null
websocket走网关后,开始报这个错!
2023-03-30 20:11:25.182 ERROR 21676 --- [ctor-http-nio-4] o.s.w.s.adapter.HttpWebHandlerAdapter : [737ff8d7-2] Error [java.lang.UnsupportedOperationException] for HTTP GET "/platform-merchant/hk_ws?hk_user_token=eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNjAyNDk3ODA2NTAzOTAzMjMyIiwibWVyY2hhbnRJZCI6IjE2MDI0OTkxMDU2MDE0ODY4NDgiLCJrZXkiOiI3MTc4ODY0Mjc3MjQ0ZDBhYWNlZDIwMjlhYzg2NGYwYyJ9.uMKehcdCjILsyBGiE7DulAA02Uur9ntHiibwuDRcxBo", but ServerHttpResponse already committed (200 OK)
2023-03-30 20:11:25.188 ERROR 21676 --- [ctor-http-nio-4] r.n.http.server.HttpServerOperations : [id: 0x737ff8d7, L:/192.168.3.52:9090 - R:/192.168.3.52:55782] Error finishing response. Closing connection
java.lang.UnsupportedOperationException: null
at org.springframework.http.ReadOnlyHttpHeaders.put(ReadOnlyHttpHeaders.java:126) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/platform-merchant/hk_ws?hk_user_token=eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxNjAyNDk3ODA2NTAzOTAzMjMyIiwibWVyY2hhbnRJZCI6IjE2MDI0OTkxMDU2MDE0ODY4NDgiLCJrZXkiOiI3MTc4ODY0Mjc3MjQ0ZDBhYWNlZDIwMjlhYzg2NGYwYyJ9.uMKehcdCjILsyBGiE7DulAA02Uur9ntHiibwuDRcxBo" [ExceptionHandlingWebHandler]
Stack trace:
at org.springframework.http.ReadOnlyHttpHeaders.put(ReadOnlyHttpHeaders.java:126) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory.dedupe(DedupeResponseHeaderGatewayFilterFactory.java:149) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory.dedupe(DedupeResponseHeaderGatewayFilterFactory.java:132) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory$1.lambda$filter$0(DedupeResponseHeaderGatewayFilterFactory.java:93) ~[spring-cloud-gateway-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:73) ~[reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:32) ~[reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:135) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.Mono.subscribe(Mono.java:4218) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) [reactor-core-3.3.5.RELEASE.jar:3.3.5.RELEASE]
网上找答案,意思是要把gateway跨域配置去掉,检查了代码,果然有跨域配置;注释掉后重启,上面报的错解决了!
@Configuration
public class GwCorsFilter {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration corsConfig = new CorsConfiguration();
List<String> allowedHeaders = Arrays.asList("x-auth-token", "content-type", "X-Requested-With", "XMLHttpRequest", "Authorization");
List<String> exposedHeaders = Arrays.asList("x-auth-token", "content-type", "X-Requested-With", "XMLHttpRequest", "Authorization");
List<String> allowedMethods = Arrays.asList("POST", "GET", "DELETE", "PUT", "OPTIONS");
List<String> allowedOrigins = Collections.singletonList("*");
corsConfig.setAllowedHeaders(allowedHeaders);
corsConfig.setAllowedMethods(allowedMethods);
corsConfig.setAllowedOrigins(allowedOrigins);
corsConfig.setExposedHeaders(exposedHeaders);
corsConfig.setMaxAge(36000L);
corsConfig.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", corsConfig);
return new CorsWebFilter(source);
}
}
原本以为就此大功告成,轻松解决;最后被告知,要留下跨域的配置,前端就是需要跨域。。。
诶呀!领导一开始没规划好路径,只能硬着头皮解决。尝试留着跨域配置,解决websocket连接报错的问题!
最后调试源码,还真发现问题了
无法推断Vary,header不支持Vary
操作,检查了一下果然有这个配置
想起来之前看过Spring Cloud Gateway官方文档,有这个介绍DedupeResponseHeader
怎么配置。
支持RETAIN_FIRST
,RETAIN_LAST
,RETAIN_UNIQUE
,没有Vary
相关配置
最后找了配置的同事,是2年前配置上去,也不知从那里抄来的!!!当时不是很清楚每一项配置,之前也一直没出问题,直到接入websocket
+跨域配置
一起才出现问题。所以加每一个配置项都要很清楚它的作用,否则不知什么时候出问题!