3

I am having following URL

http://context_path/info/abc/def

which gets converted like

http://context_path/info/abc%2Fdef

Where as my controller mapping is:

@RequestMapping(value = "/info/{id}", method = RequestMethod.GET)

here 'id' contains forward slash (/). So when I hit the URL I get 400 Bad Request.

I know the possible solutions

  • Setting tomcat to allow forward slash.
  • Use URL encoding.
  • Use of @RequestParam instead of @PathVariable.

But above solution are not possible for me.

Q. Is there any other solution like (using regular expression or changing the mapping or anything else) to the problem ? Also how the tomcat treats other special characters ('.' , ''' , ':' , ',') correctly and controller gets hit but not for '/'.

Tried but not working :

1) @RequestMapping(value = "/info/{id:.*}", method = RequestMethod.GET)
2) @RequestMapping(value = "/info/{id}/**", method = RequestMethod.GET)
3) @RequestMapping(value = "/info/**", method = RequestMethod.GET)
SuhasD
  • 728
  • 2
  • 7
  • 20

3 Answers3

1

It is not nice, but you can use Base64 transformation.

So you client will send an encoded id and you decode it back in your controller.

import org.apache.commons.codec.binary.Base64;

@RequestMapping(value = "/info/{id}", method = RequestMethod.GET)
public String get(@PathVariable String id) {
    final String realId = new String(new Base64(true).encodeBase64URLSafe(id));
    [...]
}

EDIT: You should use url save implementation of Base64:

Community
  • 1
  • 1
alex
  • 8,904
  • 6
  • 49
  • 75
  • This won't work. Spring will decode or unescape the mapping url and then try to invoke the handler method based on resulting URL. Therefore it will return as bad request. – ScanQR Nov 30 '16 at 09:41
  • @TechBreak did you tried it? I'm tried right now and it works. – alex Nov 30 '16 at 10:05
  • @dit Base64 works well but just issue it if the id contains '?' then it converts it into '/'. Any other encoder who doesnt use '/' for encoding ? – SuhasD Nov 30 '16 at 11:55
  • 1
    @SuhasD use `URL save base64` implementation from Apache: http://stackoverflow.com/questions/5641303/base64url-in-java – alex Nov 30 '16 at 12:04
  • 1
    @dit new Base64(true) works for me. thanx. I used .encodeBase64URLSafe() method instead of just .encode() to remove "\r" and "\n". http://stackoverflow.com/questions/19952621/is-it-ok-to-remove-newline-in-base64-encoding/37734981#37734981 – SuhasD Dec 01 '16 at 05:20
0

You can use something like this How to handle requests that includes forward slashes (/)?

But it has it's limitations, I would suggest you to replace the forward slash with something else like '#' while calling the api and then again replace it back to forward slash before processing it in rest controller.

If replacing while calling the api is not possible then you can use filter and replace the data there.

Community
  • 1
  • 1
Avinash
  • 4,115
  • 2
  • 22
  • 41
-1

You can use regular expressions to define your url. Refer http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-uri-templates-regex

user1211
  • 1,507
  • 1
  • 18
  • 27
  • i added following Reg-EX [\\[\\]A-Za-z0-9 \"',():._^-]+. It works for all other special characters except '/' and if I modify above Reg-EX like [\\/\\[\\]A-Za-z0-9 \"',():._^-]+ then no URL is working (even those which are working with old Reg-EX) – SuhasD Nov 30 '16 at 09:28