What's the proper way to set the Location header for an HTTP 201 response in a Java Servlet application

前端 未结 5 1486
醉梦人生
醉梦人生 2021-01-31 02:49

Consider the following code sending an HTTP 201 \"Created\" response to the client:

    String url = \"/app/things?id=42\"; // example
    response.setStatus(Htt         


        
相关标签:
5条回答
  • 2021-01-31 03:19

    Unfortunately, the servlet API does not provide a method which directly returns the absolute URL up to with the context root. For that I have several times had to use a combination of getRequestURL(), getRequestURI() and getContextPath().

    String absoluteContextRootURL = request.getRequestURL().toString().replace(request.getRequestURI().substring(1), request.getContextPath());
    
    0 讨论(0)
  • 2021-01-31 03:20

    Just send the absolute path. The restriction to an absolute URI is a known defect in RFC 2616 and will be fixed in HTTPbis (see http://trac.tools.ietf.org/wg/httpbis/trac/ticket/185).

    Please note that RFC 7231 now includes relative URIs in the spec. See other answers for how to handle relative URIs.

    0 讨论(0)
  • 2021-01-31 03:20

    Decided to go with Julian Reschke's advice and violate the spec! At least I added the following comment:

            /* 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);
    

    The reason I don't want to send the absolute URI myself is because I have seen problems with this when behind load-balancers and other production infrastructure. Although in dev mode "http://localhost:8080/foo" tends to work fine :))

    Will accept Julian's answer now ...

    0 讨论(0)
  • 2021-01-31 03:25

    You might try

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

    That will at least be smart about canonicalizing away any .. or other oddities. Other than that, I don't think it's much better than string manipulation.

    0 讨论(0)
  • 2021-01-31 03:35

    In case you are using JAX RS, there is a method in javax.ws.rs.core.Response which automatically converts relative URLs:

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

    Create a new ResponseBuilder for a created resource, set the location header using the supplied value.

    Parameters:

    • location - the URI of the new resource. If a relative URI is supplied it will be converted into an absolute URI by resolving it relative to the request URI.

    Note however that there is a bug in the JAX RS implementation CXF which leads to incorrect absolute URLs.

    0 讨论(0)
提交回复
热议问题