2012-06-21 13 views
14

Tener un método como este:Tomcat, JAX-RS, Jersey, @PathParam: ¿cómo pasar puntos y barras?

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

¿Cómo pasar un valor como "test./test"?

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

Pero si lo hago name = URLDecoder.decode(name); imprime /test y la primera parte de test. desaparece.

Ya hay una o dos preguntas como estas pero son viejas y no se encontró una buena solución, pensé que volvería a preguntar.

Respuesta

21

El patrón en el @Path anotación se volvió internamente en una expresión regular, con los elementos de plantilla a juego únicamente caracteres seleccionados por defecto. En particular, normalmente no coincide con/ caracteres; eso es casi siempre lo correcto (ya que le permite colocar plantillas en el camino) pero en este caso no es porque quiere consumir la ruta completa . Para obtener todo, tenemos que anular el fragmento de expresión regular para esa plantilla en particular; esto es en realidad bastante fácil, ya que sólo hay que poner en la plantilla de fragmentar un : seguido por el RE que queremos utilizar:

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

Esto corresponderá con todos los caracteres después de la /name/ (hasta, pero no incluyendo cualquier consulta ? parte) pero solo coincidirá si hay algo allí en absoluto. Tenga en cuenta que si tiene otras cosas acerca de @Path("/name/..."), ¡las cosas pueden ser realmente confusas! Entonces no hagas eso.

+1

¡Funciona! Puede pasar cualquier cantidad de barras, todas son capturadas sin problemas. ¿Funcionará esto con todas las implementaciones JAX-RS o cómo funciona jersey? De cualquier manera, muchas gracias, resolvió mi problema. –

+1

@Maxim Creo que es estándar, y lo uso con Apache CXF. –

+0

Se ve bien, pero parece que las barras diagonales no coinciden con esta expresión regular ... – Ievgen

0

intente especificar el tipo de codificación, las siguientes obras para mí con /name/test.%252Ftest:

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

Works! Se agregó codificación y se convierte "test.% 252Ftest" en "test./test", no solo "/ test". ¡Gracias! –

5

Si usa tomcat, y quiere pasar / en pathparam. además de las cosas @Path("/name/{name:.+}") como dijo "Donal Fellows", debe agregar -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true a sus argumentos de jvm, consulte también tomcat security-howto.

+0

No lo necesito siempre que la ruta realmente contenga un '/', y no uno codificado. –

0

Glassfish v4 acepta scape codificado para slash% 2f. Entonces podemos pasar la prueba de cadena codificada.% 2Ftest y obtener el resultado test./test usando URLDecoder.decode (name, "UTF-8"). Creo que esta es una solución mejor, especialmente cuando tienes muchos params en una solicitud. Usar la ruta @Path ("/ name/{name:. +}") Es una gran solución cuando tenemos pocos parámetros en una solicitud.

El uso de% 252f complica la solicitud del cliente porque se necesitan para construir la cadena de solicitud de codificación manualmente. Con glassfish v4 es fácil usar la codificación porcentual con URLEncoder.encode en el cliente y URLDecoder.decode en el servidor para cadenas deseadas. La mayoría de los lenguajes de programación tienen codificación porcentual y decodificación, por lo tanto, es la solución perfecta.

me trataron permitir barra codificada en GlassFish v3, pero sin éxito, aquí es el sintaxe Probé utiliza

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

Conjunto de comandos ejecutado exitosamente.

Saludos Cassio Seffrin

Cuestiones relacionadas