Spring #RequestMapping and trailing slash - spring

I am trying to map a method in a Controller using the annotation with URI template:
#RequestMapping(value="/select/{customerNumber}/{resource}", method=RequestMethod.GET)
It appears that this does not get mapped if there is a trailing slash at the end of "resource".
Update: Using Spring 3.0.2 release
Update 2: #RequestMapping seems to behave differently for URI templates vs where I don't use template. For non-template, it does not work if I have a trailing slash. But for templates it does not work if I don't have a trailing slash. Very strange!

This is fixed in 3.0.3 release. SPR-7064

Related

Why is plus(+) decoded to space ( ) in url path with springboot rest controller?

When calling GET http://localhost:8080/things/ZhaD2lk27XQPRJtwrABltd+UTWXcbnY%2FTrpxGP7VDVo= my Spring Boot application RestController with a request handler like this:
#RequestMapping("/things/{thingId}")
public ResponseEntity<Thing> getThing(
#PathVariable String thingId) {
System.out.println("thingId=" + thingId);
...
results in the following being printed ZhaD2lk27XQPRJtwrABltd UTWXcbnY/TrpxGP7VDVo= instead of what I would have expected ZhaD2lk27XQPRJtwrABltd+UTWXcbnY/TrpxGP7VDVo=.
As you can see, the plus is being turned into a space. This should not happen with the path part, only the query part. This is why the Spring UriComponentsBuilder.build().encode() I'm using to build the URL doesn't turn the plus into %2B.
I needed to tweak the application already to get the encoded slash (/) to work. See REST Endpoint unreachable if ID in URL contains %2F for details.
I'm using SpringBoot 1.4.4.RELEASE which uses Tomcat embed 8.5.11.
I have tried calling the service from Spring RestTemplate, Postman and Chrome. Same results in all cases, the plus is turned into a space
I was able to resolve after identifying that my IDE had automagically added spring-boot-starter-undertow to the POM file. I did not exclude spring-boot-starter-tomcat from spring-boot-starter-web so I'm not sure what was happening under the covers but removing the spring-boot-starter-undertow dependency fixed the issue.

Spring boot embedded tomcat behaves differently to standalone

I have a Spring boot application that exposes a REST API via Spring MVC.
When I run my application locally using the embedded tomcat I can access resources with a trailing slash on the end - e.g POST /resource/
However, when I deploy the war to a standalone tomcat instance, I get a 404 if I include the trailing slash on the URL, but a success without the trailing slash - e.g POST /resource.
The embedded tomcat works with or without the trailing slash.
My request mapping is
#RequestMapping(value = "/resource", method = RequestMethod.POST)
I've tried all sorts of configuration options including
#Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseRegisteredSuffixPatternMatch(true);
matcher.setUseTrailingSlashMatch(true);
}
The only difference I can see is the embedded tomcat is v8 and the standalone is v7. Both running the exact same sourcecode but behaving differently.
Can anyone advise on how to correct this issue?
Thanks
I was able to resolve the issue. For anyone else finding this post...
For some reason, Tomcat 7 was trying to map requests with a trailing slash to a welcome file (index.jsp). It also does not recognise the endpoint if the request contains a trailing slash unless you specifically set a request mapping for "/" despite the setUseTrailingSlashMatch match to true.
This behavior was not mirrored in my embedded tomcat (v8).
I resolved the issue by removing the welcome files from the web.xml and updating my request mapping to:
#RequestMapping(value = {"/resource","/resource/"}, method = RequestMethod.POST)

How would I escape HTML in SpringBoot's #PathVariable?

I am using Spring 4.2.5 and I just want to escape the HTML in the URL if present. Using JSON deserializer is affecting the values of RequestBody/Param as well, but I don't want other values to be changed. What is the correct way to do this?
Apache's URL builder escapes html in parameters automatically:
http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html
If you're talking about html in the spring Rest controller, a filter or Jackson configuration should solve your problem.
I guess I need to use PropertyEditorSupport class to escape the HTML in the PathVariable and implement JSON deserializer for the RequestBody.

automatic trailing slash redirection with Spring MVC

I'd like to configure Spring MVC to do the following for me:
If (a controller is not found
&& controller exist for requestURI with or without trailing slash) {
redirect 301 to other URI with or without trailing slash
} else {
return 404 error
}
The above should be done by spring, not by some web.xml filter since only spring can test whether a redirect makes sense, i.e. whether there is a controller to handle the redirected request.

Spring: Difference of /** and /* with regards to paths

What's the difference between two asterisks instead of one asterisk when we refer to paths?
Earlier I was debugging my Spring 3 project. I was trying to add a .swf using
<spring:url var="flashy" value="/resources/images/flash.swf"/>
With my web.xml's ResourceServlet looking like
<servlet-name>Resource Servlet </servlet-name>
<url-pattern>/resources/*</url-pattern>
But unfortunately I was getting this error:
WARN org.springframework.js.resources.ResourceServlet - An attempt to access a protected resource at /images/flash.swf was disallowed.
I found it really strange since all my images in the images folder were accessed but how come my .swf was "protected"?
Afterwards, I decided to change the /resources/* to /resources/** and it finally worked. My question is... why?
This is a path pattern that is used in Apache Ant library. Spring team implements it and uses it throughout the framework.
Back to your problem. According to the Javadoc for AntPathMatcher, it only has 3 rules:
? matches one character
* matches zero or more characters
** matches zero or more 'directories' in a path
UPDATE 2022
In the latest Spring Framework versions there is a forth rule:
{spring:[a-z]+} matches the regexp [a-z]+ as a path variable named "spring"
See the details in the latest (as of now) Spring Framework version 5 Javadoc: AntPathMathcer.

Resources