Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';这是在Javaservlet应用程序中为HTTP201响应设置位置头的正确方法_Java_Http_Servlets_Http Headers_Httpresponse - Fatal编程技术网

什么';这是在Javaservlet应用程序中为HTTP201响应设置位置头的正确方法

什么';这是在Javaservlet应用程序中为HTTP201响应设置位置头的正确方法,java,http,servlets,http-headers,httpresponse,Java,Http,Servlets,Http Headers,Httpresponse,考虑以下代码向客户端发送HTTP 201“已创建”响应: String url = "/app/things?id=42"; // example response.setStatus(HttpServletResponse.SC_CREATED); response.setContentType("text/plain"); response.setHeader("Location", url); response.getWriter().print(u

考虑以下代码向客户端发送HTTP 201“已创建”响应:

    String url = "/app/things?id=42"; // example
    response.setStatus(HttpServletResponse.SC_CREATED);
    response.setContentType("text/plain");
    response.setHeader("Location", url);
    response.getWriter().print(url);
它通知客户端已创建了一个新的“东西”,并且可以在URL
/app/things?id=42
中找到它。问题是这个URL是相对的。这对于JSP来说是完美的,JSP可以编写如下:

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

       Location: http://www.w3.org/pub/WWW/People.html
我的问题是,如何以适合servlet的方式将相对URL转换为位置头的解析URL

我不相信使用:

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

这是正确的解决方案。应该有一个标准的方法来生成正确的输出(以便可以应用URL重写等)。我不想创建一个hack。

不幸的是,servlet API没有提供一个直接返回到上下文根的绝对URL的方法。为此,我多次不得不使用和的组合

你可以试试

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

这至少在规范化任何
或其他古怪事物方面是明智的。除此之外,我不认为它比字符串操作好多少。

只需发送绝对路径即可。对绝对URI的限制是RFC2616中的一个已知缺陷,将在HTTPbis中修复(请参阅)


请注意,RFC 7231现在在中包含相对URI。有关如何处理相对URI,请参阅其他答案。

决定听从Julian Reschke的建议,违反规范!至少我添加了以下评论:

        /* 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);
我不想自己发送绝对URI的原因是,当我在负载平衡器和其他生产基础设施后面时,我发现了这个问题。虽然处于开发模式“http://localhost:8080/foo“往往效果很好:))


现在将接受Julian的答案…

如果您使用的是JAX RS,
javax.ws.RS.core.Response
中有一个方法:

publicstaticresponse.ResponseBuilder已创建(java.net.URI位置)

为已创建的资源创建新的ResponseBuilder,使用提供的值设置位置标头

参数:

  • location
    -新资源的URI。如果提供了相对URI,则通过相对于请求URI解析它,将其转换为绝对URI

但是请注意,JAX RS实现CXF中存在一个bug。

一旦发布了HTTPbis规范,您就不会再违反适用规范。请注意,RFC 7231现在在规范中包括相对URI,请参阅:“字段值由单个URI引用组成。当它具有相对引用的形式时([RFC3986],第4.2节),通过根据有效请求URI解析它来计算最终值([RFC3986],第5节)。”
String absoluteContextRootURL = request.getRequestURL().toString().replace(request.getRequestURI().substring(1), request.getContextPath());
new URL(new URL(request.getRequestURL().toString()), url).toString();
        /* 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);