Reputation: 6602
I want to be able to intercept the first request a client makes to my endpoint so to be able to answer with 101 (websocket estabilished) or deny it.
Is there any interceptor I can use? I tried registering a filter bean but it seems it is just skipped, I think because I'm in a webflux application...
@Bean
public FilterRegistrationBean<ContextFilter> initialFilter() {
FilterRegistrationBean<ContextFilter> registrationBean
= new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(1);
return registrationBean;
}
and
public class MyFilter extends OncePerRequestFilter{
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
log.info("You know, for filtering");
filterChain.doFilter(request, response);
}
Upvotes: 4
Views: 1114
Reputation: 1920
You can intercept the first request by implementing WebSocketHandler
and using ServerHttpRequest
you can access headers and query parameters from the request and can modify the response using ServerHttpResponse
to return a 101
status code.
import io.rsocket.RSocket;
import io.rsocket.core.RSocketServer;
import io.rsocket.transport.netty.server.CloseableChannel;
import io.rsocket.transport.netty.server.WebsocketServerTransport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class WebSocketConfig {
@Bean
public RSocket rSocket() {
// Your RSocket bean configuration
return RSocketServer.create()
.bind(WebsocketServerTransport.create("localhost", 8080))
.start()
.block();
}
@Bean
public HandlerMapping webSocketHandlerMapping() {
Map<String, WebSocketHandler> map = new HashMap<>();
map.put("/rsocket", new CustomWebSocketHandler());
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(1);
mapping.setUrlMap(map);
return mapping;
}
@Bean
public WebSocketHandlerAdapter handlerAdapter() {
return new WebSocketHandlerAdapter();
}
private static class CustomWebSocketHandler implements WebSocketHandler {
@Override
public CloseableChannel handle(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
// Access headers and query parameters here
String headerValue = serverHttpRequest.getHeaders().getFirst("your-header");
String queryParamValue = serverHttpRequest.getQueryParams().getFirst("your-query-param");
// Modify the response to return 101 status code
serverHttpResponse.setStatusCode(HttpStatus.SWITCHING_PROTOCOLS);
// Implement your logic here
return null; // Return the CloseableChannel or handle as needed
}
}
}
Upvotes: 0
Reputation: 1776
To establish the RSocket connection client must send a first frame called SETUP frame. You can catch it with the Spring @ConnectMapping
annotation.
@ConnectMapping
fun onConnect(rSocketRequester: RSocketRequester, clientId: String) {
if (clientId == "wrong_client") rSocketRequester.rsocket().dispose() //to reject connection
}
To reject the connection use the rSocketRequester.rsocket().dispose()
as shown above.
Note that with the SETUP frame you can pass the payload and metadata from the client as usual.
Upvotes: 1