spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.53k stars 3.33k forks source link

Proxy websocket wss:// to ws:// spring cloud gateway #2427

Closed intumba closed 8 months ago

intumba commented 3 years ago

500 Server Error for HTTP GET "/stomp" I have an instance of Unsecured ActiveMQ-5.16.0 and I want to route secured websocket to ActiveMQ using Spring Cloud Gateway. I have tried the solution using the documentation from Spring Cloud and I get the following issue:

500 Server Error for HTTP GET "/stomp".

Any idea why I am getting java.lang.ClassCastException

Route builder config code snippet

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {

    @Bean
    public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route(r -> r.path("/stomp/**")
                        .filters(f -> f
                                .rewritePath("/stomp/?(?<segment>.*)", "/$\\{segment}")
                                .addRequestHeader("Sec-WebSocket-Protocol", "v10.stomp, v11.stomp")
                        )
                        .uri("ws://localhost:61614"))
                .build();
    }
}

Stacktrace:

2021-11-03 07:08:27.245 ERROR 5200 --- [io-8443-exec-10] a.w.r.e.AbstractErrorWebExceptionHandler : [d9a04a]  500 Server Error for HTTP GET "/stomp"

java.lang.ClassCastException: org.apache.catalina.connector.ResponseFacade cannot be cast to reactor.netty.http.server.HttpServerResponse
        at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.getNativeResponse(ReactorNettyRequestUpgradeStrategy.java:93) ~[spring-webflux-5.2.3.RELEASE.jar:5.2.3.RELEASE]
        Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
        |_ checkpoint ? org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.ui.LogoutPageGeneratingWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.ui.LoginPageGeneratingWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.csrf.CsrfWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
        |_ checkpoint ? org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
        |_ checkpoint ? HTTP GET "/stomp" [ExceptionHandlingWebHandler]
Stack trace:
                at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.getNativeResponse(ReactorNettyRequestUpgradeStrategy.java:93) ~[spring-webflux-5.2.3.RELEASE.jar:5.2.3.RELEASE]
                at org.springframework.web.reactive.socket.server.upgrade.ReactorNettyRequestUpgradeStrategy.upgrade(ReactorNettyRequestUpgradeStrategy.java:77) ~[spring-webflux-5.2.3.RELEASE.jar:5.2.3.RELEASE]
                at org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService.lambda$handleRequest$1(HandshakeWebSocketService.java:235) ~[spring-webflux-5.2.3.RELEASE.jar:5.2.3.RELEASE]
                at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:151) ~[reactor-core-3.3.2.RELEASE.jar:3.3.2.RELEASE]
                at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) ~[reactor-core-3.3.2.RELEASE.jar:3.3.2.RELEASE]
                at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:48) ~[reactor-core-3.3.2.RELEASE.jar:3.3.2.RELEASE]
                at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.3.2.RELEASE.jar:3.3.2.RELEASE]
                at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.3.2.RELEASE.jar:3.3.2.RELEASE]
                at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.3.2.RELEASE.jar:3.3.2.RELEASE]
                at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.3.2.RELEASE.jar:3.3.2.RELEASE]
                at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.3.2.RELEASE.jar:3.3.2.RELEASE]
spencergibb commented 3 years ago

Can you describe your setup more? Where does org.apache.catalina.connector.ResponseFacade come from?

intumba commented 3 years ago

@spencergibb the org.apache.catalina.connector.ResponseFacade is coming from Active MQ 5.16.0 and I tried even using a simple java websocket server custom app, the outcome is the same.

I am using Active MQ 5.16.0 standalone server for my web socket [ws://localhost:61614/stomp/queue/test]. I used the sample provided by Active MQ stomp example.

I use spring-cloud-gateway to proxy the unsecured Active MQ standalone behind the secured gateway. I then route the wss:// to ws:// using spring cloud.

I have a simple HTTPS client running on https://localhost:8443/index.html which try to connect to Active MQ ws://localhost:61614/stomp/queue/test through the proxy at wss://localhost:8443/

I have created a repo of this sample code: https://github.com/intumba/spring-cloud-gateway and I got this sample code from the github repos.

Hope this describes my use case.

yj-cactus commented 2 years ago

I am facing the exact same issue.

spencergibb commented 8 months ago

Sorry for the late reply. If this still happens with Spring Boot 3.2 and Cloud 2023.0 we can reopen and assess.