eclipse-vertx / vert.x

Vert.x is a tool-kit for building reactive applications on the JVM
http://vertx.io
Other
14.25k stars 2.07k forks source link

SockJSHandler return a strange bad response under CORS #3738

Closed Dustone-JavaWeb closed 3 years ago

Dustone-JavaWeb commented 3 years ago

Version

4.0.0

Context

I had created a webshell with SockJSHandler, In some reason, It should be CORS, So I created a preprocessor to change the origin, The code like this.

The route

        router.route("/terminal/*").handler(this::changeOrigin);
        router.route("/mqttProxy/*").handler(this::changeOrigin);
        router.route("/terminal/*").handler(socketJSHandler);
        router.route("/mqttProxy/*").handler(socketJSHandler);

The preprocessor

    private void changeOrigin(RoutingContext context) {
        context.response().putHeader("Access-Control-Allow-Origin", context.request().getHeader("Origin"));
        context.next();
    }

Init the handler

        SockJSHandlerOptions options = new SockJSHandlerOptions().setHeartbeatInterval(2000).setRegisterWriteHandler(true).setLocalWriteHandler(true);
//        SockJSHandlerOptions options = new SockJSHandlerOptions().setHeartbeatInterval(2000);
        SockJSHandler socketJSHandler = SockJSHandler.create(vertx, options);
        // SocketJs
        Router socketRouter =socketJSHandler.socketHandler(sockJSSocket -> {
            String uri = sockJSSocket.uri();
            if (uri == null) return;
            if (uri.startsWith("/terminal")) {
                systemContext.getWebShellHandler().registerSocket(sockJSSocket);
            } else {
                systemContext.dataBus.mqttClientProxy.registerSocket(sockJSSocket);
            }
        });

I have bind the sockjs channel with local SSH channel ,so I setRegisterWriteHandler(true),to get an id。 It works well on Vertx 3.9.5 but failed with a strange error when handshake on 4.0.0。 image image

Extra

Running on. JDK 8u201 Windows 10 & armV7.

How to fix this? Thanks a lot.

pmlopes commented 3 years ago

@Dustone-JavaWeb what is the error exactly? Is it, that you set the header:

"Access-Control-Allow-Origin" : request.origin

But the server returns:

*

? Or is it something else? If you want to fully control the CORS of a request you should use the CORSHandler instead of your custom function. The reason is that the CORSHandler processes all the headers and validates then and signals the current route that it has checked the CORS headers. With this information, the Sockjs handler will not set any default headers like the * your're seeing.

Also note that your requests are setting the Referrer-Policy to strict-origin-when-crossing-origin which may affect how the browser sends the origin header back to the server. In this mode under certain circumstances the header is partial or even not sent at all:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy

Dustone-JavaWeb commented 3 years ago

@pmlopes I'm sorry that I forgot to say that before, I have been config the CORS Hanlder for all requests on 3.9.5, but it doesn't work , so I add custom function to make the origin into same, Now this function lose efficacy on 4.0.0. And the strange Referrer-Policy strict-origin-when-crossing-origin is added by deffault in SockJS lib running on frontend. The whole code like this

       Set<String> allowedHeaders = new HashSet<>();
        allowedUploadTags = new HashSet<>();
        // allow the headers
        allowedHeaders.add("Origin");
        allowedHeaders.add("Access-Control-Request-Headers");
        allowedHeaders.add("Access-Control-Allow-Headers");
        allowedHeaders.add("DNT");
        allowedHeaders.add("X-Requested-With");
        allowedHeaders.add("X-Mx-ReqToken");
        allowedHeaders.add("Keep-Alive");
        allowedHeaders.add("User-Agent");
        allowedHeaders.add("If-Modified-Since");
        allowedHeaders.add("Cache-Control");
        allowedHeaders.add("Content-Type");
        allowedHeaders.add("Accept");
        allowedHeaders.add("Connection");
        allowedHeaders.add("Cookie");
        allowedHeaders.add("X-XSRF-TOKEN");
        allowedHeaders.add("X-CSRF-TOKEN");
        allowedHeaders.add("Authorization");
//        allowedHeaders.add()
        Set<HttpMethod> allowedMethods = new HashSet<>();
        allowedMethods.add(HttpMethod.GET);
        allowedMethods.add(HttpMethod.POST);
        allowedMethods.add(HttpMethod.DELETE);
        allowedMethods.add(HttpMethod.PATCH);
        allowedMethods.add(HttpMethod.OPTIONS);
        allowedMethods.add(HttpMethod.PUT);
        allowedMethods.add(HttpMethod.UPDATE);
        allowedMethods.add(HttpMethod.MERGE);
        allowedMethods.add(HttpMethod.ACL);
        allowedMethods.add(HttpMethod.MKWORKSPACE);
        allowedMethods.add(HttpMethod.MOVE);
        allowedMethods.add(HttpMethod.HEAD);
        allowedMethods.add(HttpMethod.TRACE);
        allowedMethods.add(HttpMethod.CONNECT);

        allowedUploadTags.add(".jpg");
        allowedUploadTags.add(".png");
        allowedUploadTags.add(".js");
        allowedUploadTags.add(".json");
        allowedUploadTags.add(".css");
        allowedUploadTags.add(".zip");
        allowedUploadTags.add(".svg");
        systemContext.setVertx(vertx);

        //Config the SockJs Handler
        SockJSHandlerOptions options = new SockJSHandlerOptions().setHeartbeatInterval(2000).setRegisterWriteHandler(true).setLocalWriteHandler(true);
//        SockJSHandlerOptions options = new SockJSHandlerOptions().setHeartbeatInterval(2000);
        SockJSHandler socketJSHandler = SockJSHandler.create(vertx, options);
        // SocketJs
        Router socketRouter =socketJSHandler.socketHandler(sockJSSocket -> {
            String uri = sockJSSocket.uri();
            if (uri == null) return;
            if (uri.startsWith("/terminal")) {
                systemContext.getWebShellHandler().registerSocket(sockJSSocket);
            } else {
                systemContext.dataBus.mqttClientProxy.registerSocket(sockJSSocket);
            }
        });

        Router router = Router.router(vertx);
        router.route().handler(CorsHandler.create("*").allowedMethods(allowedMethods).allowedHeaders(allowedHeaders).allowCredentials(false));
        router.route("/terminal/*").handler(this::changeOrigin);
        router.route("/mqttProxy/*").handler(this::changeOrigin);
        router.route("/terminal/*").handler(socketJSHandler);
        router.route("/mqttProxy/*").handler(socketJSHandler);

    private void changeOrigin(RoutingContext context) {
        context.response().putHeader("Access-Control-Allow-Origin", context.request().getHeader("Origin"));
        context.next();
    }
vietj commented 3 years ago

I will close this issue as it is not related. to vertx-core and seems to be a question