Accessing HTTP connection headers and path

Hi,

its me again. We are using websocket connection transport. We know how to set HTTP transport headers on client side via

WebsocketServerTransport.create(dipHostname, dipPort).setTransportHeaders()

But I have no idea how to read/validate these headers when creating RSocket server and how to make it accessible in acceptor method. I would like to know how to access the HTTP headers and URL of the HTTP request that initiated the websocket.

RSocketFactory.receive()
            .acceptor((setup, sendingSocket) -> { ...

The idea is that two types of clients will connect to the server, I need to distinquish between them and handle the sockets differently.

Thanks
Matous

Hi,

@OlehDokuka should be able to help you out with this question. He has worked on the WebSocket transport recently.

Thanks,
Robert

Hi @MavoCz!

I created a straightforward sample for you on how you can treat headers in case of WebSocket transport.

@robertroeser do we want to have a better way to challenge incoming headers in case of WebSocket transport?

Regards,
Oleh

@OlehDokuka I guess it depends on if this helps @MavoCz with his use-case.

Hi, thanks for answer and solution. It works and it was easy enough to implement. I can define multiple routes with different RSocket acceptor in each of them. We will need the authentication too, so that is a nice bonus.

I guess that we should also use the FragmentationDuplexConnection to avoid the 64K bug that we were reporting in another thread?

As for the API, its strange that I can easily set the headers in WebsocketClientTransport, but I can not validate them in WebsocketServerTransport. A decent factory/builder for server would be much appreciated as right now it does not do much. We also plan to add SSL, HTTP header Authentication, maybe compression. And I guess once you get past proof of concept, every project will want to use these features when using websocket transport.

We have seen that @OlehDokuka allready implemented much of that in

So we will probably take inspiration from there.

@OlehDokuka Thanks for the example, this is very helpful. One thing though, is it somehow possible to intercept the close codes on the client side? I’ll elaborate a bit.

Let’s say I have header check on one side of the connection and I wish to return a valid websocket close code, e.g. 1011 or similar, see 7.4.1. Defined Status Codes.

routes.ws("/", (in, out) -> {
    if (in.headers().containsValue("Authorization", "test", true)) {
        DuplexConnection connection = new WebsocketDuplexConnection((Connection) in);
    	return acceptor.apply(connection).then(out.neverComplete());
    }
    	
    return out.sendClose(1011);
})

Is it possible to somehow access the close code on the other side of the connection? I found rSocket.onClose() method, unfortunately it provides no details.

RSocket rSocket = RSocketFactory.connect()
	            .keepAliveAckTimeout(Duration.ofMinutes(10))
	            .frameDecoder(PayloadDecoder.ZERO_COPY)
	            .transport(clientTransport2)
	            .start()
	            .block();
	
// expect error here because of closed channel
rSocket.requestResponse(payload1).block();

The code above is taken from the example you provided. The last line causes exception due to closed socket, however it would be extremely useful to be able to extract the close code, so that we can react accordingly (e.g. attempt to reconnect, or exit the application if the error is unrecoverable).

Any ideas how to tackle the problem?

Thanks,
Matej

Alright, I see your point.

I will provide a few changes at the API level which should simplify of handling of such things.

Let me take a little of time to create a PR and discuss that with @robertroeser afterwards .

Regards,
Oleh

Excellent, thanks for the prompt reaction! Looking forward for any news.

Regards,
Matej

Any ETA on this? We have some work that is blocked on this. Is that possible with current API? Or do we have to wait on API change?
Thanks
Matous