Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

URLs containing %2F (forward slash) are not mapped correctly to @RequestMapping methods [SPR-11101] #15727

Closed
spring-projects-issues opened this issue Nov 20, 2013 · 16 comments

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Nov 20, 2013

Rodion opened SPR-11101 and commented

Controller method:

@RequestMapping(value = "/test_url_decoding/{param1}")
public String[] testUrlDecoding(@PathVariable("param1") String p1)

Call:
/test_url_decoding/a%2Fb

Expecting result: parameter p1 is set to "a/b".
Current result: 404 Not found.

Simular problem:
http://stackoverflow.com/questions/13482020/encoded-slash-2f-with-spring-requestmapping-path-param-gives-http-400

The problem was already discussed in https://jira.springsource.org/browse/SPR-7919

Suggested solution (setting decodeUrl of the HandlerMapping to false) does not work. The UrlPathHelper uses HttpServletRequest.getServletPath() method internally, which decodes the path.

Suggested implementation for non-decoding helper:

public class UrlPathHelperNonDecoding extends UrlPathHelper {

	public UrlPathHelperFixed() {
		super.setUrlDecode(false);
	}
	
	@Override
	public void setUrlDecode(boolean urlDecode) {
		if (urlDecode) {
			throw new IllegalArgumentException("Handler does not support URL decoding.");
		}
	}

	@Override
	public String getServletPath(HttpServletRequest request) {
		String servletPath = getOriginatingServletPath(request);
		return servletPath;
	}
	

	@Override
	public String getOriginatingServletPath(HttpServletRequest request) {
		String servletPath = request.getRequestURI().substring(request.getContextPath().length());
		return servletPath;
	}
}

context.xml

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
  <property name="order" value="-1"></property>
  <property name="urlPathHelper">
    <bean class="com.yoochoose.frontend.spring.UrlPathHelperFixed"/>
  </property>
</bean>

Affects: 3.2.5

Issue Links:

  • #12574 Request mapping using @PathVariable doesn't work with URL-encoded values
  • #20202 [doc] Document urlDecode=false implies alwaysUseFullPath=true

Referenced from: commits 12598f8, d55a173

Backported to: 3.2.8

3 votes, 10 watchers

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Dec 5, 2013

Mike Noordermeer commented

Seems a valid bug to me.

You can work around it by setting:

requestMappingHandlerMapping.setAlwaysUseFullPath(true)

This assumes you are mapping the DispatcherServlet to /.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 7, 2014

Tyrone Walker commented

Where would you set this for the work-around?

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 7, 2014

Mike Noordermeer commented

See https://gist.github.com/MikeN123/8873622 for a sample where we workaround the various 'bugs' in the URL processing. It's a BeanPostProcessor where we postprocess the RequestMappingHandlerMappings.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 7, 2014

Juergen Hoeller commented

Rossen, anything we could do about this in the short term, i.e. for 4.0.2 - maybe a flag on mvc:annotation-driven?

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 10, 2014

Rossen Stoyanchev commented

Mike Noordermeer, <mvc:annotation-driven> element now allows setting various path-related settings including a custom UrlPathHelper so you should no longer need the BeanPostProcessor. See this example configuration. This is a very recent change that was included in 4.0.1.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 10, 2014

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 10, 2014

Mike Noordermeer commented

Yes thanks (but it doesn't really make a difference code-wise, since I still need an extra class - either a fixed UrlPathHelper, or a BeanPostProcessor).

The original bug report about UrlPathHelper is still valid though. The MVC tags don't need a flag to solve this, but it should simply use the correct path. Currently it uses request.getServletPath(), which always returns decoded path, even if urlDecode = false.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 10, 2014

Rossen Stoyanchev commented

I can confirm the issue as described by Rodion. HttpServletRequest.getServletPath() does indeed decode the servlet path and that interferes with attempts to determine the request mapping path when UrlPathHelper.urlDecode=false.

The crucial bit is mentioned by Mike Noordermeer. When the DispatcherServlet is mapped to "/" the entire path (following the context path) is considered the servlet path -- compare that to servlet mappings by prefix (e.g. "/app/*") where the servlet path is fixed. In this case setting UrlPathHelper.alwaysUseFullPath=true (as Mike suggested) addresses the issue since it doesn't rely on getting the servlet path and it's fine to use since since there is no servlet prefix.

Of course it's not at all obvious that urlDecode=false also requires alwaysUseFullPath=false where the DispatcherServlet is mapped to "/". The Servlet API however still doesn't provide a way to find out how a servlet is mapped. We clearly need a solution.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 10, 2014

Rossen Stoyanchev commented

I have added a fix that ensures the right behavior when urlDecode is set to false. Please see commit 12598f.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Feb 12, 2014

daniel carter commented

Interesting that no one has mentioned here that most servers refuse requests with %2F in them due to CVE-2007-0450 That seems a bit of overkill to me and the correct solution would have been to make sure the security constraints take account of %2F in contexts where it will be interpreted as a path separator.

Anyway, took me a while to find, so in case it helps anyone else, to allow %2F in paths in tomcat, set this system property.

-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 16, 2015

Selvakumar Subramanian commented

Hi Rossen,
We are using Spring 3.2 and sample url and method are below
Url : localhost:8090/RecordCenter/customers/SSR%2FC2/divisions
Method:
@RequestMapping(value = "/customers/{customerId}/divisions", method = RequestMethod.GET)
public @ResponseBody
DivisionsDto getAllDivisions(@PathVariable String customerId) {
/*customerId is matched against DB */
DivisionsDto divisionsDto = divsionDao.getDivisions(customerId);
return divisionsDto;
}

The issue that we have is
1.While resolving the path to a request mapper we do not want URL to be decoded (No Decode)
2.However while the path variable is injected into the method, we need that to be decoded as it would not match it is encoded. (Decode)

Apache CXF does this automatically (I do not remember setting any special config)

Setting UrlPathHelper.urlDecode = false, does the #1 but #2 is not satisfied. Is there a setting that we can use to satisfy the scenario.
We have a lot of methods and we do not want to use URLDecoder.decode() for all path variables in each method.

Please advise.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 17, 2015

Rossen Stoyanchev commented

The behavior you describe is how it should behave, see #13736. I'm not sure what the issue is. Demonstrate perhaps, sample project or use spring-framework-issues.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 18, 2015

Selvakumar Subramanian commented

Rossen, I was able to decode the pathVariables using an interceptor. I did not know a different way to do it but is working for us now.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 18, 2015

Rossen Stoyanchev commented

Good, however my point was that you shouldn't have to do that. They should be decoded. If you want to demonstrate the issue, I'd be happy to take a look.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 19, 2015

Selvakumar Subramanian commented

Having some issues in creating a sample project. Will upload by this weekend with Spring 3.2.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Apr 6, 2016

Rodrigo commented

Hi!, I am having the same issue. Could you please share the Interceptor you used to decode the path variables? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants