RESTlet appears to be doubly decoding my form parameters
-
28-05-2021 - |
题
I have a RESTlet application embedded in a Tomcat server and clients are complaining that % symbols in @FormParm parameters are doubly decoded in the RESTlet framework causing a server error 500.
My questions are: Do the clients need to doubly encode percent symbols (e.g. send xx%2525xx to represent the five character sequence "xx%xx")? If so, is this a bug in the RESTlet framework or the common way of encoding form parameters? If not, how am I misusing the RESTlet framework?
My API looks like
//... 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 ....
}
A curl command like:
curl -H "Accept: application/json" -d "name=100%25+working" http://${host}/api/sessionx21/foo/home/
Generates a server-side stack trace that looks like:
Apr 2, 2012 5:15:20 PM org.restlet.ext.jaxrs.internal.util.ExceptionHandler methodInvokeException WARNING: Can not invoke the resource method java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape (%) pattern - For input string: " w" at java.net.URLDecoder.decode(URLDecoder.java:173) at org.restlet.data.Reference.decode(Reference.java:170) at org.restlet.data.Reference.decode(Reference.java:143) at org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList$AbstractParamGetter.convertParamValue(ParameterList.java:186) at 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) at org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList$FormParamGetter.getParamValue(ParameterList.java:561) at org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList$AbstractParamGetter.getValue(ParameterList.java:409) at org.restlet.ext.jaxrs.internal.wrappers.params.ParameterList.get(ParameterList.java:1096) at org.restlet.ext.jaxrs.internal.wrappers.AbstractMethodWrapper.internalInvoke(AbstractMethodWrapper.java:166)
My pom.xml file contains
<repository>
<id>maven-restlet</id>
<name>Public online Restlet repository</name>
<url>http://maven.restlet.org</url>
</repository>
....
<jaxb.version>2.1</jaxb.version>
解决方案
I know this question posted long time ago, but maybe someone will still find it useful. I had the same problem today.
After digging the restlet code - it seems like there is a bug of url-decoding the parameters twice. Workaround for this is to annotate the method with @Encoded. This annotation mark not to decode the paramaters, so it will only be decoded once.
@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 ....
}
其他提示
I know this is a very old question, but the issue still exists in Restlet's JAX-RS implementation today. It's definitely a bug, so I've formalized a bug report with Restlet. Here's to hoping it will be fixed in an upcoming release!
Bug report with all relevant implementation details here:
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4375&dsMessageId=3091010
i run into this bug,too.my solution is changed the pom dependency from restlet-ext-jaxrs 2.0.9 to restlet-ext-jaxrs 2.0.9-snapshot.the diference of these two jar file is the ParameterList class' AbstractParamGetter method.The former one has the external code snippet:
if(decode() && paramValue != null)
paramValue = Reference.decode(paramValue);