Browse Source

Fix issue w/ use of UrlPathHelper's urlDecode property

Before this change the getPathWithinServletMapping method of
UrlPathHelper could not work properly when a default servlet mapping
(i.e. "/") was used in combination with urlDecode=false. The fact that
the getServletPath() method of HttpServletRequest always returns a
decoded path was getting in the way.

Although there is no way to check Servlet mappings through the Servlet
API, this change aims to detect the given scenario and returns the full
path following the context path thus avoiding URL decoding.

Note that the same can be achieved by setting urlDecode=false and
alwaysUseFullPath=true. However this change ensures that urlDecode
works properly without having to know that.

Issue: SPR-11101
(cherry picked from commit 12598f8)
pull/465/head
Juergen Hoeller 12 years ago
parent
commit
d55a173e2e
  1. 35
      spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java
  2. 22
      spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java

35
spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@ -22,11 +22,11 @@ import java.util.LinkedHashMap; @@ -22,11 +22,11 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
@ -181,11 +181,24 @@ public class UrlPathHelper { @@ -181,11 +181,24 @@ public class UrlPathHelper {
}
else {
// Special case: URI is different from servlet path.
// Can happen e.g. with index page: URI="/", servletPath="/index.html"
// Use path info if available, as it indicates an index page within
// a servlet mapping. Otherwise, use the full servlet path.
String pathInfo = request.getPathInfo();
return (pathInfo != null ? pathInfo : servletPath);
if (pathInfo != null) {
// Use path info if available. Indicates index page within a servlet mapping?
// e.g. with index page: URI="/", servletPath="/index.html"
return pathInfo;
}
if (!this.urlDecode) {
// No path info... (not mapped by prefix, nor by extension, nor "/*")
// For the default servlet mapping (i.e. "/"), urlDecode=false can
// cause issues since getServletPath() returns a decoded path.
// If decoding pathWithinApp yields a match just use pathWithinApp.
path = getRemainingPath(decodeInternal(request, pathWithinApp), servletPath, false);
if (path != null) {
return pathWithinApp;
}
}
// Otherwise, use the full servlet path.
return servletPath;
}
}
@ -217,7 +230,7 @@ public class UrlPathHelper { @@ -217,7 +230,7 @@ public class UrlPathHelper {
private String getRemainingPath(String requestUri, String mapping, boolean ignoreCase) {
int index1 = 0;
int index2 = 0;
for ( ; (index1 < requestUri.length()) && (index2 < mapping.length()); index1++, index2++) {
for (; (index1 < requestUri.length()) && (index2 < mapping.length()); index1++, index2++) {
char c1 = requestUri.charAt(index1);
char c2 = mapping.charAt(index2);
if (c1 == ';') {
@ -244,7 +257,7 @@ public class UrlPathHelper { @@ -244,7 +257,7 @@ public class UrlPathHelper {
else if (requestUri.charAt(index1) == ';') {
index1 = requestUri.indexOf('/', index1);
}
return (index1 != -1) ? requestUri.substring(index1) : "";
return (index1 != -1 ? requestUri.substring(index1) : "");
}
/**
@ -299,8 +312,7 @@ public class UrlPathHelper { @@ -299,8 +312,7 @@ public class UrlPathHelper {
if (servletPath == null) {
servletPath = request.getServletPath();
}
if (servletPath.length() > 1 && servletPath.endsWith("/") &&
shouldRemoveTrailingServletPathSlash(request)) {
if (servletPath.length() > 1 && servletPath.endsWith("/") && shouldRemoveTrailingServletPathSlash(request)) {
// On WebSphere, in non-compliant mode, for a "/foo/" case that would be "/foo"
// on all other servlet containers: removing trailing slash, proceeding with
// that remaining slash as final lookup path...
@ -436,7 +448,6 @@ public class UrlPathHelper { @@ -436,7 +448,6 @@ public class UrlPathHelper {
* Remove ";" (semicolon) content from the given request URI if the
* {@linkplain #setRemoveSemicolonContent(boolean) removeSemicolonContent}
* property is set to "true". Note that "jssessionid" is always removed.
*
* @param requestUri the request URI string to remove ";" content from
* @return the updated URI string
*/
@ -473,7 +484,6 @@ public class UrlPathHelper { @@ -473,7 +484,6 @@ public class UrlPathHelper {
* assumed the URL path from which the variables were extracted is already
* decoded through a call to
* {@link #getLookupPathForRequest(HttpServletRequest)}.
*
* @param request current HTTP request
* @param vars URI variables extracted from the URL path
* @return the same Map or a new Map instance
@ -498,7 +508,6 @@ public class UrlPathHelper { @@ -498,7 +508,6 @@ public class UrlPathHelper {
* assumed the URL path from which the variables were extracted is already
* decoded through a call to
* {@link #getLookupPathForRequest(HttpServletRequest)}.
*
* @param request current HTTP request
* @param vars URI variables extracted from the URL path
* @return the same Map or a new Map instance

22
spring-web/src/test/java/org/springframework/web/util/UrlPathHelperTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@ -32,11 +32,12 @@ import static org.junit.Assert.*; @@ -32,11 +32,12 @@ import static org.junit.Assert.*;
*/
public class UrlPathHelperTests {
private static final String WEBSPHERE_URI_ATTRIBUTE = "com.ibm.websphere.servlet.uri_non_decoded";
private UrlPathHelper helper;
private MockHttpServletRequest request;
private static final String WEBSPHERE_URI_ATTRIBUTE = "com.ibm.websphere.servlet.uri_non_decoded";
@Before
public void setUp() {
@ -44,6 +45,7 @@ public class UrlPathHelperTests { @@ -44,6 +45,7 @@ public class UrlPathHelperTests {
request = new MockHttpServletRequest();
}
@Test
public void getPathWithinApplication() {
request.setContextPath("/petclinic");
@ -77,6 +79,17 @@ public class UrlPathHelperTests { @@ -77,6 +79,17 @@ public class UrlPathHelperTests {
assertEquals("Incorrect path returned", "/welcome.html", helper.getPathWithinServletMapping(request));
}
@Test // SPR-11101
public void getPathWithinServletWithoutUrlDecoding() {
request.setContextPath("/SPR-11101");
request.setServletPath("/test_url_decoding/a/b");
request.setRequestURI("/test_url_decoding/a%2Fb");
helper.setUrlDecode(false);
String actual = helper.getPathWithinServletMapping(request);
assertEquals("/test_url_decoding/a%2Fb", actual);
}
@Test
public void getRequestUri() {
request.setRequestURI("/welcome.html");
@ -141,11 +154,10 @@ public class UrlPathHelperTests { @@ -141,11 +154,10 @@ public class UrlPathHelperTests {
//
// suite of tests root requests for default servlets (SRV 11.2) on Websphere vs Tomcat and other containers
// see: http://jira.springframework.org/browse/SPR-7064
// Suite of tests root requests for default servlets (SRV 11.2) on WebSphere vs Tomcat and other containers
// See: http://jira.springframework.org/browse/SPR-7064
//
//
// / mapping (default servlet)
//

Loading…
Cancel
Save