9

I have a GET method

@RequestMapping(
        value = "/path/{field}",
        method = RequestMethod.GET
)
public void get(@PathVariable String field) {
}

Field can contain slashes, like "some/thing/else" which results in the path not being found. It could even be something like "//////////////". Some examples:

www.something.com/path/field //works
www.something.com/path/some/thing
www.something.com/path///////////

I've tried with {field:.*} and escaping the slash with %2F but it still won't reach the method. Some help?

Alex Parvan
  • 413
  • 1
  • 4
  • 16
  • If field2 contains a /, it's not the same url though. Is that the expected behaviour? – Turtle Jul 12 '17 at 08:36
  • 1
    Possible duplicate of [How to handle requests that includes forward slashes (/)?](https://stackoverflow.com/questions/31421061/how-to-handle-requests-that-includes-forward-slashes) – ares Jul 12 '17 at 08:37
  • It's not, my field can contain any number of slashes, it could even be "/////////////". – Alex Parvan Jul 12 '17 at 08:46
  • 4
    I think you'll have to handle `/path1/**` and then parse the whole path yourself. – Jeremy Grand Jul 12 '17 at 08:48

3 Answers3

17

I've solved the problem, for Spring Boot. First you have to configure Spring to allow encoded slashes.

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Bean
    public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
        DefaultHttpFirewall firewall = new DefaultHttpFirewall();
        firewall.setAllowUrlEncodedSlash(true);
        return firewall;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
    }
}

Then you need to allow it from the embedded tomcat:

public class Application extends WebMvcConfigurerAdapter {

    public static void main(String[] args) {
        System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setUrlDecode(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

Although this works, the best way to do it is to just use query parameters instead.

Alex Parvan
  • 413
  • 1
  • 4
  • 16
3

As JeremyGrand suggested you could match route by using ** and then parse path by yourself:

@GetMapping("/path/**")
public String test(HttpServletRequest request) {
    return request.getRequestURI(); //do some kind of parsing
}
Krzysztof Atłasik
  • 21,985
  • 6
  • 54
  • 76
  • The example i gave was a simplification, the actual url is something like: /path1/field1/path2/field2/path3/field3. Doing /path1/** seems like a hack in this case. – Alex Parvan Jul 12 '17 at 12:15
  • @AlexParvan From your question, it looks like you want that. Otherwise, you would be able to use multiple '@PathVariable' variables. – Tigerware Apr 10 '21 at 02:15
1

I hit a problem like this sometime back. Looks like I resolved it in the following manner.

@RequestMapping(value = "/{field:.*}")
...
String requestedField = URLDecoder.decode(field)
Mike Holdsworth
  • 1,088
  • 11
  • 12
  • 2
    As i said, i tried using {field:.*} but i only get a 404, code String requestedField = URLDecoder.decode(field) is never reached. – Alex Parvan Jul 12 '17 at 12:20