Tomcat、JAX-RS、Jersey、@PathParam:如何传递点和斜杠?

15

有一个像这样的方法:

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

我如何传递像 "test./test" 这样的值?

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

但如果我执行 name = URLDecoder.decode(name),它会打印出 /test,而test.的第一部分会消失。

已经有一个或两个类似的问题了,但它们都很老了,没有找到好的解决方案,所以我想再问一次。

4个回答

21

@Path注释中的模式会被内部转换成一个正则表达式,它的模板部分默认只匹配选定的字符。特别地,通常它们不匹配/字符;这几乎总是正确的做法(因为它允许您在路径中间放置模板),但在这种情况下它不是,因为您想要消耗整个后续路径。要获取所有内容,我们必须覆盖该特定模板的正则表达式片段;这实际上非常容易,因为我们只需在模板片段中放置:,后跟我们想要使用的正则表达式即可:

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

这将匹配在/name/后面的所有字符(直到但不包括任何?查询部分),但只有在那里确实有东西时才能匹配。请注意,如果您还有其他的@Path("/name/...")代码存在,事情可能会变得非常混乱!所以不要那样做。


1
可以工作!可以通过任意数量的斜杠,所有内容都能被很好地捕获。这个方法是否适用于所有JAX-RS实现或者只适用于Jersey?无论如何,非常感谢,它解决了我的问题。 - Maxim Suponya
1
@Maxim 我认为这是标准的,并且我将其与Apache CXF一起使用。 - Donal Fellows
看起来不错,但是这个正则表达式似乎无法匹配反斜杠。 - Zhenya

6
如果您正在使用Tomcat,并且想要在pathparam中传递/,除了像"Donal Fellows"所说的那样使用@Path("/name/{name:.+}"),您还应该将-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true添加到您的jvm参数中。有关详细信息,请参见tomcat security-howto

只要路径中确实包含 / 而不是编码后的路径,我就不需要它。 - Donal Fellows

0

尝试指定编码类型,以下代码对我有效:/name/test.%252Ftest

System.out.println(URLDecoder.decode(name, "UTF-8"));
return URLDecoder.decode(name, "UTF-8");

可以了!添加了编码后,它将“test.%252Ftest”转换为“test./test”,而不仅仅是“/test”。谢谢! - Maxim Suponya

0

Glassfish v4接受斜杠%2f的编码转义。然后我们可以传递编码字符串test.%2Ftest并使用URLDecoder.decode(name,“UTF-8”)获得结果test./test。我认为这是一个更好的解决方案,特别是当您在一个请求中有许多参数时。当我们在请求中有少量参数时,使用@Path(“/ name / {name:.+}”)路径是很好的解决方案。

使用%252f会使客户端请求变得复杂,因为需要手动构造编码请求字符串。在glassfish v4中,使用URLEncoder.encode在客户端和URLDecoder.decode在服务器上使用百分比编码来实现所需的字符串非常容易。大多数编程语言都具有百分比编码和解码功能,因此这是完美的解决方案。

我尝试启用glassfish v3中的编码斜杠,但没有成功,以下是我尝试使用的语法

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

命令设置成功执行。

问候 Cassio Seffrin


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接