Spring MVC @PathVariable getting truncated

Viewed 78582

I have a controller that provides RESTful access to information:

@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request,
                            HttpServletResponse response) {

The problem I am experiencing is that if I hit the server with a path variable with special characters it gets truncated. For example: http://localhost:8080/blah-server/blah/get/blah2010.08.19-02:25:47

The parameter blahName will be blah2010.08

However, the call to request.getRequestURI() contains all the information passed in.

Any idea how to prevent Spring from truncating the @PathVariable?

16 Answers

I also ran into the same issue, and setting the property to false didn't help me either. However, the API says:

Note that paths which include a ".xxx" suffix or end with "/" already will not be transformed using the default suffix pattern in any case.

I tried adding "/end" to my RESTful URL, and the problem went away. I'm not please with the solution, but it did work.

BTW, I don't know what the Spring designers were thinking when they added this "feature" and then turned it on by default. IMHO, it should be removed.

If you can edit the address that requests are sent to, simple fix would be to add a trailing slash to them (and also in the @RequestMapping value):

/path/{variable}/

so the mapping would look like:

RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/")

See also Spring MVC @PathVariable with dot (.) is getting truncated.

The problem that you are facing is due to spring interpreting the last part of the uri after the dot (.) as a file extension like .json or .xml . So when spring tries to resolve the path variable it simply truncates the rest of the data after it encounters a dot (.) at the end of the uri. Note: also this happens only if you keep the path variable at the end of the uri.

For example consider uri : https://localhost/example/gallery.df/link.ar

@RestController
public class CustomController {
    @GetMapping("/example/{firstValue}/{secondValue}")
    public void example(@PathVariable("firstValue") String firstValue,
      @PathVariable("secondValue") String secondValue) {
        // ...  
    }
}

In the above url firstValue = "gallery.df" and secondValue="link" , the last bit after the . gets truncated when the path variable gets interpreted.

So, to prevent this there is two possible ways:

1.) Using a regexp mapping

Use a regex at the end part of mapping

@GetMapping("/example/{firstValue}/{secondValue:.+}")   
public void example(
  @PathVariable("firstValue") String firstValue,
  @PathVariable("secondValue") String secondValue) {
    //...
}

By using + , we indicate any value after the dot will also be part of the path variable.

2.) Adding a slash at the end of our @PathVariable

@GetMapping("/example/{firstValue}/{secondValue}/")
public void example(
  @PathVariable("firstValue") String firstValue,
  @PathVariable("secondValue") String secondValue) {
    //...
}

This will enclose our second variable protecting it from Spring’s default behavior.

3) By overriding Spring's default webmvc configuration

Spring provides ways to override the default configurations that gets imported by using the annotations @EnableWebMvc.We can customize the Spring MVC configuration by declaring our own DefaultAnnotationHandlerMapping bean in the application context and setting its useDefaultSuffixPattern property to false. Example:

@Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {

    @Bean
    public RequestMappingHandlerMapping 
      requestMappingHandlerMapping() {

        RequestMappingHandlerMapping handlerMapping
          = super.requestMappingHandlerMapping();
        handlerMapping.setUseSuffixPatternMatch(false);
        return handlerMapping;
    }
}

Keep in mind that overriding this default configuration, affects all urls.

Note : here we are extending the WebMvcConfigurationSupport class to override the default methods. There is one more way to override the deault configurations by implementing the WebMvcConfigurer interface. For more details on this read : https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html

Related