servlet filters example cookie java http servlets http-headers httpresponse

java - example - servlets filters



¿Cuál es la forma correcta de configurar el encabezado de ubicación para una respuesta HTTP 201 en una aplicación Java Servlet? (5)

Considere el siguiente código enviando una respuesta HTTP 201 "Creado" al cliente:

String url = "/app/things?id=42"; // example response.setStatus(HttpServletResponse.SC_CREATED); response.setContentType("text/plain"); response.setHeader("Location", url); response.getWriter().print(url);

Informa al cliente que se creó una nueva "cosa" y que se puede encontrar en la URL /app/things?id=42 . El problema es que esta URL es relativa. Esto sería perfecto para un JSP, que podría escribirse de la siguiente manera:

<img src="<c:url value="/things?id=42" />" />

Que produciría el siguiente HTML:

<img src="/app/things?id=42" />

Que es lo que queremos para las aplicaciones web.

Pero no creo que eso sea lo que queremos para un encabezado de Ubicación de respuesta 201. La especificación HTTP states :

14.30 Ubicación

El campo del encabezado de respuesta de ubicación se usa para redirigir al destinatario a una ubicación distinta de URI de solicitud para completar la solicitud o identificar un nuevo recurso. Para 201 (respuestas creadas), la ubicación es la del nuevo recurso creado por la solicitud. Para las respuestas 3xx, la ubicación DEBERÍA indicar el URI preferido del servidor para la redirección automática al recurso. El valor del campo consiste en un solo URI absoluto.

Location = "Location" ":" absoluteURI

Un ejemplo es:

Location: http://www.w3.org/pub/WWW/People.html

Mi pregunta es cómo puedo traducir esa URL relativa a la URL abosolute para el encabezado de ubicación de la manera adecuada para los servlets.

NO creo que el uso de:

request.getServerName() + ":" + request.getServerPort() + url;

Es la solución correcta Debe haber un método estándar que produzca el resultado correcto (para que se pueda aplicar la reescritura de URL, etc.). No quiero crear un truco.


¡Decidió seguir el consejo de Julian Reschke y violar las especificaciones! Al menos agregué el siguiente comentario:

/* Note: strictly speaking (per section 14.30 of RFC 2616), the Location header * requires an *absolute URI*. However, in practice, many web * applications send an *absolute path* instead. This is interoperable, * that is, works in popular web browsers (according to * http://en.wikipedia.org/wiki/HTTP_location). * * As the information required to set the Location header to an absolute URI * is not generally available to a Servlet, we go with the flow and send * an absolute path instead (in violation of RFC 2616). * * There is an issue filed with Hypertext Transfer Protocol Bis (httpbis) * working group to resolve this problem here: * http://trac.tools.ietf.org/wg/httpbis/trac/ticket/185 */ response.setHeader("Location", url);

La razón por la que no deseo enviar el URI absoluto es porque he visto problemas con esto cuando estaba detrás de balanceadores de carga y otra infraestructura de producción. Aunque en modo dev "http: // localhost: 8080 / foo" tiende a funcionar bien :))

Aceptaré la respuesta de Julian ahora ...


En caso de que esté utilizando JAX RS, hay un método en javax.ws.rs.core.Response que convierte automáticamente las URL relativas :

public static Response.ResponseBuilder created(java.net.URI location)

Cree un nuevo ResponseBuilder para un recurso creado, establezca el encabezado de ubicación usando el valor proporcionado.

Parámetros:

  • location : el URI del nuevo recurso. Si se suministra un URI relativo, se convertirá en un URI absoluto resolviéndolo en relación con el URI de solicitud.

Sin embargo, tenga en cuenta que hay un error en la implementación de JAX RS CXF que conduce a direcciones URL absolutas incorrectas .


Lamentablemente, la API de servlet no proporciona un método que devuelva directamente la URL absoluta hasta con la raíz de contexto. Para eso, he tenido que usar varias veces una combinación de getRequestURL() , getRequestURI() y getContextPath() .

String absoluteContextRootURL = request.getRequestURL().toString().replace(request.getRequestURI().substring(1), request.getContextPath());


Puede intentar

new URL(new URL(request.getRequestURL().toString()), url).toString();

Eso al menos será inteligente acerca de canonicalizar cualquier .. u otras rarezas. Aparte de eso, no creo que sea mucho mejor que la manipulación de cadenas.