/** * Returns "this" instance if the request matches all expressions; * or {@code null} otherwise. */ @Override @Nullable public HeadersRequestCondition getMatchingCondition(ServerWebExchange exchange) { if (CorsUtils.isPreFlightRequest(exchange.getRequest())) { return PRE_FLIGHT_MATCH; } for (HeaderExpression expression : this.expressions) { if (!expression.match(exchange)) { return null; } } return this; }
/** * Checks if any of the contained media type expressions match the given * request 'Content-Type' header and returns an instance that is guaranteed * to contain matching expressions only. The match is performed via * {@link MediaType#includes(MediaType)}. * @param exchange the current exchange * @return the same instance if the condition contains no expressions; * or a new condition with matching expressions only; * or {@code null} if no expressions match. */ @Override public ConsumesRequestCondition getMatchingCondition(ServerWebExchange exchange) { if (CorsUtils.isPreFlightRequest(exchange.getRequest())) { return PRE_FLIGHT_MATCH; } if (isEmpty()) { return this; } Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<>(this.expressions); result.removeIf(expression -> !expression.match(exchange)); return (!result.isEmpty() ? new ConsumesRequestCondition(result) : null); }
@Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(exchange); if (corsConfiguration != null) { boolean isValid = this.processor.process(corsConfiguration, exchange); if (!isValid || CorsUtils.isPreFlightRequest(request)) { return Mono.empty(); } } } return chain.filter(exchange); }
logger.trace(exchange.getLogPrefix() + matches.size() + " matching mappings: " + matches); if (CorsUtils.isPreFlightRequest(exchange.getRequest())) { return PREFLIGHT_AMBIGUOUS_MATCH;
@Nullable public ProducesRequestCondition getMatchingCondition(ServerWebExchange exchange) { if (CorsUtils.isPreFlightRequest(exchange.getRequest())) { return PRE_FLIGHT_MATCH;
@Override public boolean process(@Nullable CorsConfiguration config, ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); if (!CorsUtils.isCorsRequest(request)) { return true; } if (responseHasCors(response)) { logger.trace("Skip: response already contains \"Access-Control-Allow-Origin\""); return true; } if (CorsUtils.isSameOrigin(request)) { logger.trace("Skip: request is from same origin"); return true; } boolean preFlightRequest = CorsUtils.isPreFlightRequest(request); if (config == null) { if (preFlightRequest) { rejectRequest(response); return false; } else { return true; } } return handleInternal(exchange, config, preFlightRequest); }
@Override public Mono<Object> getHandler(ServerWebExchange exchange) { return getHandlerInternal(exchange).map(handler -> { if (logger.isDebugEnabled()) { logger.debug(exchange.getLogPrefix() + "Mapped to " + handler); } if (CorsUtils.isCorsRequest(exchange.getRequest())) { CorsConfiguration configA = this.corsConfigurationSource.getCorsConfiguration(exchange); CorsConfiguration configB = getCorsConfiguration(handler, exchange); CorsConfiguration config = (configA != null ? configA.combine(configB) : configB); if (!getCorsProcessor().process(config, exchange) || CorsUtils.isPreFlightRequest(exchange.getRequest())) { return REQUEST_HANDLED_HANDLER; } } return handler; }); }
/** * Check if any of the HTTP request methods match the given request and * return an instance that contains the matching HTTP request method only. * @param exchange the current exchange * @return the same instance if the condition is empty (unless the request * method is HTTP OPTIONS), a new condition with the matched request method, * or {@code null} if there is no match or the condition is empty and the * request method is OPTIONS. */ @Override @Nullable public RequestMethodsRequestCondition getMatchingCondition(ServerWebExchange exchange) { if (CorsUtils.isPreFlightRequest(exchange.getRequest())) { return matchPreFlight(exchange.getRequest()); } if (getMethods().isEmpty()) { if (RequestMethod.OPTIONS.name().equals(exchange.getRequest().getMethodValue())) { return null; // No implicit match for OPTIONS (we handle it) } return this; } return matchRequestMethod(exchange.getRequest().getMethod()); }
@Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(exchange); if (corsConfiguration != null) { boolean isValid = this.processor.process(corsConfiguration, exchange); if (!isValid || CorsUtils.isPreFlightRequest(request)) { return Mono.empty(); } } } return chain.filter(exchange); }
@Override public boolean process(@Nullable CorsConfiguration config, ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); if (!CorsUtils.isCorsRequest(request)) { return true; } if (responseHasCors(response)) { logger.trace("Skip: response already contains \"Access-Control-Allow-Origin\""); return true; } if (CorsUtils.isSameOrigin(request)) { logger.trace("Skip: request is from same origin"); return true; } boolean preFlightRequest = CorsUtils.isPreFlightRequest(request); if (config == null) { if (preFlightRequest) { rejectRequest(response); return false; } else { return true; } } return handleInternal(exchange, config, preFlightRequest); }
@Test public void isNotPreFlightRequest() { ServerHttpRequest request = get("/").build(); assertFalse(CorsUtils.isPreFlightRequest(request)); request = options("/").header(HttpHeaders.ORIGIN, "http://domain.com").build(); assertFalse(CorsUtils.isPreFlightRequest(request)); request = options("/").header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").build(); assertFalse(CorsUtils.isPreFlightRequest(request)); }
@Test public void isPreFlightRequest() { ServerHttpRequest request = options("/") .header(HttpHeaders.ORIGIN, "http://domain.com") .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET") .build(); assertTrue(CorsUtils.isPreFlightRequest(request)); }
/** * Returns "this" instance if the request matches all expressions; * or {@code null} otherwise. */ @Override public HeadersRequestCondition getMatchingCondition(ServerWebExchange exchange) { if (CorsUtils.isPreFlightRequest(exchange.getRequest())) { return PRE_FLIGHT_MATCH; } for (HeaderExpression expression : expressions) { if (!expression.match(exchange)) { return null; } } return this; }
/** * Checks if any of the contained media type expressions match the given * request 'Content-Type' header and returns an instance that is guaranteed * to contain matching expressions only. The match is performed via * {@link MediaType#includes(MediaType)}. * @param exchange the current exchange * @return the same instance if the condition contains no expressions; * or a new condition with matching expressions only; * or {@code null} if no expressions match. */ @Override public ConsumesRequestCondition getMatchingCondition(ServerWebExchange exchange) { if (CorsUtils.isPreFlightRequest(exchange.getRequest())) { return PRE_FLIGHT_MATCH; } if (isEmpty()) { return this; } Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<>(expressions); for (Iterator<ConsumeMediaTypeExpression> iterator = result.iterator(); iterator.hasNext();) { ConsumeMediaTypeExpression expression = iterator.next(); if (!expression.match(exchange)) { iterator.remove(); } } return (result.isEmpty()) ? null : new ConsumesRequestCondition(result); }
@Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(exchange); if (corsConfiguration != null) { boolean isValid = this.processor.process(corsConfiguration, exchange); if (!isValid || CorsUtils.isPreFlightRequest(request)) { return Mono.empty(); } } } return chain.filter(exchange); }
@Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(exchange); if (corsConfiguration != null) { boolean isValid = this.processor.process(corsConfiguration, exchange); if (!isValid || CorsUtils.isPreFlightRequest(request)) { return Mono.empty(); } } } return chain.filter(exchange); }
@Override public boolean process(@Nullable CorsConfiguration config, ServerWebExchange exchange) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); if (!CorsUtils.isCorsRequest(request)) { return true; } if (responseHasCors(response)) { logger.trace("Skip: response already contains \"Access-Control-Allow-Origin\""); return true; } if (CorsUtils.isSameOrigin(request)) { logger.trace("Skip: request is from same origin"); return true; } boolean preFlightRequest = CorsUtils.isPreFlightRequest(request); if (config == null) { if (preFlightRequest) { rejectRequest(response); return false; } else { return true; } } return handleInternal(exchange, config, preFlightRequest); }
@Override public Mono<Object> getHandler(ServerWebExchange exchange) { return getHandlerInternal(exchange).map(handler -> { if (CorsUtils.isCorsRequest(exchange.getRequest())) { CorsConfiguration configA = this.globalCorsConfigSource.getCorsConfiguration(exchange); CorsConfiguration configB = getCorsConfiguration(handler, exchange); CorsConfiguration config = (configA != null ? configA.combine(configB) : configB); if (!getCorsProcessor().processRequest(config, exchange) || CorsUtils.isPreFlightRequest(exchange.getRequest())) { return REQUEST_HANDLED_HANDLER; } } return handler; }); }
Mono<SecurityResponse> preHandle(ServerWebExchange exchange, String id) { ServerHttpRequest request = exchange.getRequest(); if (CorsUtils.isPreFlightRequest(request)) { return SUCCESS; } if (!StringUtils.hasText(this.applicationId)) { return Mono.error(new CloudFoundryAuthorizationException( Reason.SERVICE_UNAVAILABLE, "Application id is not available")); } if (this.cloudFoundrySecurityService == null) { return Mono.error(new CloudFoundryAuthorizationException( Reason.SERVICE_UNAVAILABLE, "Cloud controller URL is not available")); } return check(exchange, id).then(SUCCESS).doOnError(this::logError) .onErrorResume(this::getErrorResponse); }
/** * Check if any of the HTTP request methods match the given request and * return an instance that contains the matching HTTP request method only. * @param exchange the current exchange * @return the same instance if the condition is empty (unless the request * method is HTTP OPTIONS), a new condition with the matched request method, * or {@code null} if there is no match or the condition is empty and the * request method is OPTIONS. */ @Override public RequestMethodsRequestCondition getMatchingCondition(ServerWebExchange exchange) { if (CorsUtils.isPreFlightRequest(exchange.getRequest())) { return matchPreFlight(exchange.getRequest()); } if (getMethods().isEmpty()) { if (RequestMethod.OPTIONS.name().equals(exchange.getRequest().getMethod().name())) { return null; // No implicit match for OPTIONS (we handle it) } return this; } return matchRequestMethod(exchange.getRequest().getMethod().name()); }