29
29
import org .springframework .context .ApplicationContextAware ;
30
30
import org .springframework .core .annotation .AnnotationAwareOrderComparator ;
31
31
import org .springframework .http .HttpStatus ;
32
- import org .springframework .http .server .reactive .ServerHttpRequest ;
33
32
import org .springframework .lang .Nullable ;
34
33
import org .springframework .util .ObjectUtils ;
35
34
import org .springframework .web .cors .reactive .CorsUtils ;
35
+ import org .springframework .web .cors .reactive .PreFlightRequestHandler ;
36
36
import org .springframework .web .server .ResponseStatusException ;
37
37
import org .springframework .web .server .ServerWebExchange ;
38
38
import org .springframework .web .server .WebHandler ;
53
53
*
54
54
* <p>{@code DispatcherHandler} is also designed to be a Spring bean itself and
55
55
* implements {@link ApplicationContextAware} for access to the context it runs
56
- * in. If {@code DispatcherHandler} is declared with the bean name "webHandler"
57
- * it is discovered by {@link WebHttpHandlerBuilder#applicationContext} which
58
- * creates a processing chain together with {@code WebFilter},
56
+ * in. If {@code DispatcherHandler} is declared as a bean with the name
57
+ * "webHandler", it is discovered by
58
+ * {@link WebHttpHandlerBuilder#applicationContext(ApplicationContext)} which
59
+ * puts together a processing chain together with {@code WebFilter},
59
60
* {@code WebExceptionHandler} and others.
60
61
*
61
62
* <p>A {@code DispatcherHandler} bean declaration is included in
68
69
* @since 5.0
69
70
* @see WebHttpHandlerBuilder#applicationContext(ApplicationContext)
70
71
*/
71
- public class DispatcherHandler implements WebHandler , ApplicationContextAware {
72
+ public class DispatcherHandler implements WebHandler , PreFlightRequestHandler , ApplicationContextAware {
72
73
73
74
@ Nullable
74
75
private List <HandlerMapping > handlerMappings ;
@@ -142,6 +143,9 @@ public Mono<Void> handle(ServerWebExchange exchange) {
142
143
if (this .handlerMappings == null ) {
143
144
return createNotFoundError ();
144
145
}
146
+ if (CorsUtils .isPreFlightRequest (exchange .getRequest ())) {
147
+ return handlePreFlight (exchange );
148
+ }
145
149
return Flux .fromIterable (this .handlerMappings )
146
150
.concatMap (mapping -> mapping .getHandler (exchange ))
147
151
.next ()
@@ -158,11 +162,8 @@ private <R> Mono<R> createNotFoundError() {
158
162
}
159
163
160
164
private Mono <HandlerResult > invokeHandler (ServerWebExchange exchange , Object handler ) {
161
- // No handling for CORS rejected requests and pre-flight requests
162
- ServerHttpRequest request = exchange .getRequest ();
163
- HttpStatus status = exchange .getResponse ().getStatusCode ();
164
- if (ObjectUtils .nullSafeEquals (status , HttpStatus .FORBIDDEN ) || CorsUtils .isPreFlightRequest (request )) {
165
- return Mono .empty ();
165
+ if (ObjectUtils .nullSafeEquals (exchange .getResponse ().getStatusCode (), HttpStatus .FORBIDDEN )) {
166
+ return Mono .empty (); // CORS rejection
166
167
}
167
168
if (this .handlerAdapters != null ) {
168
169
for (HandlerAdapter handlerAdapter : this .handlerAdapters ) {
@@ -196,4 +197,13 @@ private HandlerResultHandler getResultHandler(HandlerResult handlerResult) {
196
197
throw new IllegalStateException ("No HandlerResultHandler for " + handlerResult .getReturnValue ());
197
198
}
198
199
200
+ @ Override
201
+ public Mono <Void > handlePreFlight (ServerWebExchange exchange ) {
202
+ return Flux .fromIterable (this .handlerMappings != null ? this .handlerMappings : Collections .emptyList ())
203
+ .concatMap (mapping -> mapping .getHandler (exchange ))
204
+ .switchIfEmpty (Mono .fromRunnable (() -> exchange .getResponse ().setStatusCode (HttpStatus .FORBIDDEN )))
205
+ .next ()
206
+ .then ();
207
+ }
208
+
199
209
}
0 commit comments