Improve handling for pre-flight requests
1. Update the HandlerMapping contract to state that CORS checks are expected to be applied before returning a handler. 2. DispatcherHandler checks explicitly for pre-flight requests or CORS failed requests and skips handling for both. Technically no change since AbstractHandlerMapping already returns a NO_OP_HANDLER for those cases. The purpose however is for the DispatcherHandler to also guarantee more explicitly that no such handling can take place for such cases. As one consequence, this makes it possible to invoke the DispatcherHandler from anywhere in the WebFilter chain in order to "handle" a pre-flight request, and then skip the rest of the WebFilter chain. See gh-26257
This commit is contained in:
@@ -28,7 +28,10 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.reactive.result.SimpleHandlerAdapter;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.web.testfixture.method.ResolvableMethod;
|
||||
import org.springframework.web.testfixture.server.MockServerWebExchange;
|
||||
@@ -37,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
/**
|
||||
@@ -50,7 +54,7 @@ public class DispatcherHandlerTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void handlerMappingOrder() {
|
||||
void handlerMappingOrder() {
|
||||
HandlerMapping hm1 = mock(HandlerMapping.class, withSettings().extraInterfaces(Ordered.class));
|
||||
HandlerMapping hm2 = mock(HandlerMapping.class, withSettings().extraInterfaces(Ordered.class));
|
||||
given(((Ordered) hm1).getOrder()).willReturn(1);
|
||||
@@ -65,13 +69,34 @@ public class DispatcherHandlerTests {
|
||||
context.registerBean(HandlerResultHandler.class, StringHandlerResultHandler::new);
|
||||
context.refresh();
|
||||
|
||||
DispatcherHandler dispatcherHandler = new DispatcherHandler(context);
|
||||
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/"));
|
||||
dispatcherHandler.handle(exchange).block(Duration.ofSeconds(0));
|
||||
new DispatcherHandler(context).handle(exchange).block(Duration.ofSeconds(0));
|
||||
|
||||
assertThat(exchange.getResponse().getBodyAsString().block(Duration.ofSeconds(5))).isEqualTo("1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void preFlightRequest() {
|
||||
WebHandler webHandler = mock(WebHandler.class);
|
||||
HandlerMapping handlerMapping = mock(HandlerMapping.class);
|
||||
given((handlerMapping).getHandler(any())).willReturn(Mono.just(webHandler));
|
||||
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
context.registerBean("handlerMapping", HandlerMapping.class, () -> handlerMapping);
|
||||
context.registerBean(HandlerAdapter.class, SimpleHandlerAdapter::new);
|
||||
context.registerBean(HandlerResultHandler.class, StringHandlerResultHandler::new);
|
||||
context.refresh();
|
||||
|
||||
MockServerHttpRequest request = MockServerHttpRequest.options("/")
|
||||
.header(HttpHeaders.ORIGIN, "https://domain.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.build();
|
||||
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(request);
|
||||
new DispatcherHandler(context).handle(exchange).block(Duration.ofSeconds(0));
|
||||
|
||||
verifyNoInteractions(webHandler);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void handle() {}
|
||||
@@ -101,7 +126,11 @@ public class DispatcherHandlerTests {
|
||||
|
||||
@Override
|
||||
public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
|
||||
byte[] bytes = ((String) result.getReturnValue()).getBytes(StandardCharsets.UTF_8);
|
||||
Object returnValue = result.getReturnValue();
|
||||
if (returnValue == null) {
|
||||
return Mono.empty();
|
||||
}
|
||||
byte[] bytes = ((String) returnValue).getBytes(StandardCharsets.UTF_8);
|
||||
DataBuffer dataBuffer = DefaultDataBufferFactory.sharedInstance.wrap(bytes);
|
||||
return exchange.getResponse().writeWith(Mono.just(dataBuffer));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user