2

我在 Tomcat 服务器中嵌入了一个 RESTlet 应用程序,客户端抱怨 @FormParm 参数中的 % 符号在 RESTlet 框架中被双重解码,导致服务器错误 500。

我的问题是:客户端是否需要对百分比符号进行双重编码(例如发送 xx%2525xx 来表示五个字符序列“xx%xx”)?如果是这样,这是 RESTlet 框架中的错误还是编码表单参数的常用方式?如果不是,我如何滥用 RESTlet 框架?

我的 API 看起来像

//... many imports omitted.
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;

@Path("/{session}/foo/")
@Transactional(propagation = Propagation.REQUIRED)

 /**  ........
  */
public class DocumentService extends BaseService {
// ...
     */
  @POST
  @Path("/{path:.*}/")
  @Consumes({"application/x-www-form-urlencoded"})
  @Produces({"application/json"})
  public Response alterDocument(final @Context UriInfo ui, 
    final @Context HttpHeaders hh,
    final @PathParam("session") String sessionToken,
    final @PathParam("path") String path,
    @FormParam("name") String name) throws WebApplicationException {
      /// code here not reached on call described below ....
    }

一个 curl 命令,如:

curl -H "接受:应用程序/json" -d "name=100%25+working" http://${host}/api/sessionx21/foo/home/

生成如下所示的服务器端堆栈跟踪:

2012 年 4 月 2 日下午 5:15:20 org.restlet.ext.jaxrs.internal.util.ExceptionHandler methodInvokeException 警告:无法调用资源方法 java.lang.IllegalArgumentException:URLDecoder:转义 (%) 模式中的非法十六进制字符 -对于输入字符串:“w”在 java.net.URLDecoder.decode(URLDecoder.java:173) 在 org.restlet.data.Reference.decode(Reference.java:170) 在 org.restlet.data.Reference.decode( Reference.java:143) 在 org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList$AbstractParamGetter.convertParamValue(ParameterList.java:186) 在 org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList$ AbstractParamGetter.convertParamValue(ParameterList.java:166) at org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList$FormOrQueryParamGetter.getParamValue(ParameterList.java:529) 在 org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList$AbstractParamGetter.getValue( ParameterList.java:409) 在 org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList.get(ParameterList.java:1096) 在 org.restlet.ext.jaxrs.internal.wrappers.AbstractMethodWrapper.internalInvoke(AbstractMethodWrapper.爪哇:166)AbstractMethodWrapper.internalInvoke(AbstractMethodWrapper.java:166)AbstractMethodWrapper.internalInvoke(AbstractMethodWrapper.java:166)

我的 pom.xml 文件包含

    <repository>
      <id>maven-restlet</id>
      <name>Public online Restlet repository</name>
      <url>http://maven.restlet.org</url>
    </repository>
....
       <jaxb.version>2.1</jaxb.version>
4

3 回答 3

2

我知道这是一个非常古老的问题,但这个问题今天仍然存在于 Restlet 的 JAX-RS 实现中。这绝对是一个错误,所以我已经用 Restlet 正式编写了一个错误报告。这是希望它会在即将发布的版本中得到修复!

此处包含所有相关实施细节的错误报告:

http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4375&dsMessageId=3091010

于 2014-11-08T21:35:47.143 回答
1

我也遇到了这个错误。我的解决方案是将pom依赖项从restlet-ext-jaxrs 2.0.9更改为restlet-ext-jaxrs 2.0.9-snapshot。这两个jar文件的区别在于ParameterList类的AbstractParamGetter方法.前者有外部代码片段:</p>

  if(decode() && paramValue != null)
            paramValue = Reference.decode(paramValue);
于 2013-03-14T02:51:53.777 回答
1

我知道很久以前发布的这个问题,但也许有人仍然会觉得它有用。我今天遇到了同样的问题。

在挖掘了restlet代码之后 - 似乎有一个对参数进行两次url解码的错误。解决方法是使用@Encoded注释该方法。该注释标记不解码参数,因此只会解码一次。

@POST
@Path("/{path:.*}/")
@Encoded
@Consumes({"application/x-www-form-urlencoded"})
@Produces({"application/json"})
public Response alterDocument(final @Context UriInfo ui, 
  final @Context HttpHeaders hh,
  final @PathParam("session") String sessionToken,
  final @PathParam("path") String path,
  @FormParam("name") String name) throws WebApplicationException {
    /// code here not reached on call described below ....
 }
于 2012-08-14T09:44:49.630 回答