什么';这是在Javaservlet应用程序中为HTTP201响应设置位置头的正确方法
考虑以下代码向客户端发送HTTP 201“已创建”响应:什么';这是在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
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,使用提供的值设置位置标头
参数:
-新资源的URI。如果提供了相对URI,则通过相对于请求URI解析它,将其转换为绝对URIlocation
但是请注意,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);