Tomcat, JAX-RS, Jersey, @PathParam: how to pass do

2019-01-26 04:46发布

Having a method like this:

@GET @Path("/name/{name}")
@Produces(MediaType.TEXT_PLAIN)
public String getProperty(@PathParam("name") String name) {
        System.out.println(name);
}

How do I pass a value like "test./test"?

/name/test./test     gives HTTP 404
/name/test.%2Ftest   gives HTTP 400
/name/test.%252Ftest prints test%2Ftest

But if I do name = URLDecoder.decode(name); it prints /test and the first part of test. disappears.

There is one or two questions like this already but they are old and there was no good solution found, I thought I'll ask again.

4条回答
小情绪 Triste *
2楼-- · 2019-01-26 05:09

The pattern in the @Path annotation is internally turned into a regular expression, with the template parts matching only selected characters by default. In particular, they normally don't match / characters; that's almost always the right thing to do (as it lets you put templates part way through a path) but in this case it isn't as you're wanting to consume the whole subsequent path. To get everything, we have to override the regular expression fragment for that particular template; this is actually pretty easy, since we just put in the template fragment a : followed by the RE that we want to use:

@GET @Produces(MediaType.TEXT_PLAIN)
@Path("/name/{name:.+}")
public String getProperty(@PathParam("name") String name) {
    return name;
}

This will match all characters after the /name/ (up to but not including any ? query part) but will only match if there's something there at all. Be aware that if you have any other @Path("/name/...") things about, things can get really confusing! So don't do that.

查看更多
Evening l夕情丶
3楼-- · 2019-01-26 05:24

If you using tomcat, and want pass / in pathparam. besides the @Path("/name/{name:.+}") stuff as 'Donal Fellows' said, you should add -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true to your jvm arguments, see also tomcat security-howto.

查看更多
迷人小祖宗
4楼-- · 2019-01-26 05:27

Glassfish v4 accept encoded scape for slash %2f. Then we can pass the encoded String test.%2Ftest and get the result test./test using URLDecoder.decode(name, "UTF-8"). I think this is a better solution especially when you have many params in one request. Using the path @Path("/name/{name:.+}") is great solution when we have few parameters in a request.

Using %252f complicates the client request becouse are needed to contruct the encoding request String manually. With glassfish v4 it's easy to use percent encoding with URLEncoder.encode in client and URLDecoder.decode in server to wished Strings. The most programing languages has percent encoding and decoding, therefore it's perfect solution.

I tried enable encoded slash in glassfish v3 but no success, here is the sintaxe I tried used

bin\asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-1.http.encoded-slash-enabled=true configs.config.server-config.network-config.protocols.protocol.http-listener-1.http.encoded-slash-enabled=true

Command set executed successfully.

Regards Cassio Seffrin

查看更多
等我变得足够好
5楼-- · 2019-01-26 05:33

Try specifying the encoding type, the following works for me with /name/test.%252Ftest:

System.out.println(URLDecoder.decode(name, "UTF-8"));
return URLDecoder.decode(name, "UTF-8");
查看更多
登录 后发表回答