Skip to content

Decode URI variable values when UrlPathHelper.setUrlDecode() is set to false [SPR-9098] #13736

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

Closed
spring-projects-issues opened this issue Feb 8, 2012 · 6 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Feb 8, 2012

Frans Flippo opened SPR-9098 and commented

Say I have a Controller with the following request mapping:

@RequestMapping(value = "/{group}/{identifier}", method = RequestMethod.GET)

Current behavior:

If one of the PathVariable components (e.g. "identifier" in the above example) contains a URL encoded slash (%2F), the handler is NOT invoked for that request, e.g.
http://myhost/myservlet/group/a%2Fb

Expected behavior:

If one of the PathVariable comonents (e.g. "identifier" in the above example) contains a URL encoded slash (%2F), the handler is invoked for that request and the URL decoded value is assigned to the path variable, e.g.
http://myhost/myservlet/group/a%2Fb

calls the handler method above with group="group" and identifier="a/b"

This is supported by the RFC which assigns special meaning to the slash character and states a slash and a URL encoded slash are NOT the same character:

RFC 3986 says (section 2.2) :
The purpose of reserved characters is to provide a set of delimiting
characters that are distinguishable from other data within a URI.
URIs that differ in the replacement of a reserved character with its
corresponding percent-encoded octet are not equivalent. Percent-
encoding a reserved character, or decoding a percent-encoded octet
that corresponds to a reserved character, will change how the URI is
interpreted by most applications. Thus, characters in the reserved
set are protected from normalization and are therefore safe to be
used by scheme-specific and producer-specific algorithms for
delimiting data subcomponents within a URI.

The actual URL decoding happens in UrlPathHelper.getLookupPathForRequest which eventually calls getRequestUri which calls decodeAndCleanUriString. This is basically too early. First the handler should be chosen and the PathVariables assigned. Then URL decoding should happen on each of the path variables' values.

If desired I can write a unit test or include a sample Controller to reproduce the above.

Note: Tomcat MUST be started with the -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true option or the request will never even land at the Spring DispatcherServlet.


Affects: 3.1 GA

Issue Links:

Referenced from: commits 57307a0

1 votes, 3 watchers

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

The default behavior is to decode the URL prior to mapping the request. You can use the setUrlDecode(boolean) property on AbstractHandlerMapping to change this behavior and basically not decode the URL, which should make the mapping in your example work but the extracted URI variables will still be encoded. For that you can overwrite RequestMappingInforHandlerMapping.handleMatch().

@spring-projects-issues
Copy link
Collaborator Author

Frans Flippo commented

OK, that's a workable workaround for my situation.

However, wouldn't you agree the behavior I describe under "Expected behavior" should be the default, and that it would break very few installed code bases if implemented in Spring Web?

The problem with the workaround is that now my Controller class needs to have knowledge of how the HandlerMapping is configured. If urlDecode is false, it should manually decode the PathVariables' values, of urlDecode is true, it shouldn't. Not very elegant.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

We can't change the default value of urlDecode so easily I am afraid. If switched from "true" to "false", applications would need switch their mappings throughout from not encoded to encoded URL paths (the literal parts at least) -- e.g. from @RequestMapping("/foo bar") to @RequestMapping("/foo%20bar"). I do agree that when set to false, we should probably decode the path variables. I would consider that an improvement.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Modified title (from: "AbstractHandlerMethodMapping should not decode request path when finding handler but decode PathVariables individually later")

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

UrlPathHelper now includes an additional method for decoding URI path variables. It checks the urlDecode property and decodes only if false since that path (from which the variables were extracted) wouldn't have been decoded.

@spring-projects-issues
Copy link
Collaborator Author

Anthony Gerrard commented

I think this has changed the behaviour with regards to url path parameters.

e.g.
@RequestMapping("/something")

used to match
/something
and also
/something;else=true

now you get a not found for the second request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants