diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/ProducesRequestCondition.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/ProducesRequestCondition.java index 6683372e80..2148b498ca 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/ProducesRequestCondition.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/ProducesRequestCondition.java @@ -188,9 +188,12 @@ public final class ProducesRequestCondition extends AbstractRequestCondition result = getMatchingExpressions(exchange); if (!CollectionUtils.isEmpty(result)) { return new ProducesRequestCondition(result, this); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/condition/ProducesRequestConditionTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/condition/ProducesRequestConditionTests.java index 7abe05d674..d78674a56e 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/condition/ProducesRequestConditionTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/condition/ProducesRequestConditionTests.java @@ -21,7 +21,10 @@ import java.util.Collections; import org.junit.Test; +import org.springframework.http.MediaType; import org.springframework.mock.web.test.server.MockServerWebExchange; +import org.springframework.web.reactive.accept.RequestedContentTypeResolver; +import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; import org.springframework.web.server.ServerWebExchange; import static org.junit.Assert.*; @@ -129,6 +132,23 @@ public class ProducesRequestConditionTests { assertNotNull(condition.getMatchingCondition(exchange)); } + @Test // gh-22853 + public void matchAndCompare() { + RequestedContentTypeResolverBuilder builder = new RequestedContentTypeResolverBuilder(); + builder.headerResolver(); + builder.fixedResolver(MediaType.TEXT_HTML); + RequestedContentTypeResolver resolver = builder.build(); + + ProducesRequestCondition none = new ProducesRequestCondition(new String[0], null, resolver); + ProducesRequestCondition html = new ProducesRequestCondition(new String[] {"text/html"}, null, resolver); + + MockServerWebExchange exchange = MockServerWebExchange.from(get("/").header("Accept", "*/*")); + + ProducesRequestCondition noneMatch = none.getMatchingCondition(exchange); + ProducesRequestCondition htmlMatch = html.getMatchingCondition(exchange); + + assertEquals(1, noneMatch.compareTo(htmlMatch, exchange)); + } @Test public void compareTo() { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/ProducesRequestCondition.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/ProducesRequestCondition.java index 72e35b4105..c0fb6ae0f2 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/ProducesRequestCondition.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/ProducesRequestCondition.java @@ -189,10 +189,12 @@ public final class ProducesRequestCondition extends AbstractRequestCondition acceptedMediaTypes; try { acceptedMediaTypes = getAcceptedMediaTypes(request); @@ -200,7 +202,6 @@ public final class ProducesRequestCondition extends AbstractRequestCondition result = getMatchingExpressions(acceptedMediaTypes); if (!CollectionUtils.isEmpty(result)) { return new ProducesRequestCondition(result, this); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java index e38ddabd1f..96578d5198 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.web.filter.GenericFilterBean; import org.springframework.web.util.UrlPathHelper; @@ -96,6 +97,10 @@ public class ResourceUrlEncodingFilter extends GenericFilterBean { String requestUri = pathHelper.getRequestUri(this); String lookupPath = pathHelper.getLookupPathForRequest(this); this.indexLookupPath = requestUri.lastIndexOf(lookupPath); + Assert.isTrue(this.indexLookupPath != -1, () -> + "Failed to find lookupPath '" + lookupPath + "' within requestUri '" + requestUri + ". " + + "Does the path have invalid encoded characters " + + "for characterEncoding=" + getRequest().getCharacterEncoding() + "?"); this.prefixLookupPath = requestUri.substring(0, this.indexLookupPath); if ("/".equals(lookupPath) && !"/".equals(requestUri)) { String contextPath = pathHelper.getContextPath(this); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/ProducesRequestConditionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/ProducesRequestConditionTests.java index fa0c3946cd..726d15e130 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/ProducesRequestConditionTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/condition/ProducesRequestConditionTests.java @@ -23,7 +23,11 @@ import javax.servlet.http.HttpServletRequest; import org.junit.Test; +import org.springframework.http.MediaType; import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.web.accept.ContentNegotiationManager; +import org.springframework.web.accept.FixedContentNegotiationStrategy; +import org.springframework.web.accept.HeaderContentNegotiationStrategy; import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition.ProduceMediaTypeExpression; import static org.junit.Assert.*; @@ -149,6 +153,24 @@ public class ProducesRequestConditionTests { assertNotNull(condition.getMatchingCondition(request)); } + @Test // gh-22853 + public void matchAndCompare() { + ContentNegotiationManager manager = new ContentNegotiationManager( + new HeaderContentNegotiationStrategy(), + new FixedContentNegotiationStrategy(MediaType.TEXT_HTML)); + + ProducesRequestCondition none = new ProducesRequestCondition(new String[0], null, manager); + ProducesRequestCondition html = new ProducesRequestCondition(new String[] {"text/html"}, null, manager); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Accept", "*/*"); + + ProducesRequestCondition noneMatch = none.getMatchingCondition(request); + ProducesRequestCondition htmlMatch = html.getMatchingCondition(request); + + assertEquals(1, noneMatch.compareTo(htmlMatch, request)); + } + @Test public void compareTo() { ProducesRequestCondition html = new ProducesRequestCondition("text/html");