如何正确地向客户端发送HTTP消息
我正在使用Java中的REST风格的Web服务。如果出现问题,我需要一个很好的方法来向客户端发送错误消息。如何正确地向客户端发送HTTP消息
根据Javadoc,HttpServletResponse.setStatus(int status, String message)
已被弃用“由于消息参数含义不明确”。
是否有首选方法来设置响应的状态消息或“reason phrase”? sendError(int, String)
方法不会这样做。
编辑: 为了澄清,我想修改HTTP状态行,即"HTTP/1.1 404 Not Found"
,而不是正文内容。具体来说,我想发送回复如"HTTP/1.1 400 Missing customerNumber parameter"
。
我不认为任何RESTful客户端会希望看一下原因短语找出什么地方出了错;我见过/使用过的大多数RESTful服务都会在响应的主体中发送标准状态信息和扩展消息。 sendError(int, String)
非常适合这种情况。
这是不是很清楚你想要完成什么。我的第一个想法是sendError,但你说这不会做你想做的事......你是否看过创建一组“错误响应”,意思是特定的XML或JSON内容(或任何你用作传输语言的)包含错误消息或代码以及其他任何有用的信息?
我做了类似于基于Spring-mvc的RESTful服务,而且它运行良好,但是您必须捕获并处理每个异常,以防止客户端获得通用的500消息或其他东西。 Spring Exception Resolvers在这方面效果很好。
希望这有助于......如果没有,也许你想要完成什么更清晰一点。对不起,如果我正在密集和失去明显的东西。
我对REST的'最佳实践'还不是很熟悉。但我知道这个概念是基于HTTP以及它应该如何自然解决。那么如何在应用程序错误中使用MIME类型和简单文本,如'application/myapp-exception'和一些'Bla bla'?您可以为此提供一个客户端库。
我不会对应用程序错误使用HTTP响应代码。因为我想知道什么是失败的:无论是我的应用程序还是我的HTTP服务器。
(我希望,我会在这里看到一些最佳实践建议,也。)
在这种情况下,* 403 Forbidden *表示失败的HTTP服务器还是失败的应用程序?那么* 418我是一个茶壶*,如http://www.ietf.org/rfc/rfc2324.txt中所定义的那样? ;-) – Arjan 2009-07-08 23:30:06
嘿嘿,好点。但是我提出了这个解决方案,因为标题内容是有限的。所以是的,我必须纠正自己。使用响应代码来表示应用程序/服务器错误是正确的。但是由于限制(编码,长度等),我不会将错误信息与标题一起发送。为了发送错误消息本身,我建议使用MIME类型和响应主体。因此,在为客户端创建错误消息时,您的应用程序不必知道任何限制。 – cafebabe 2009-07-09 10:38:11
我认为sendError
应该这样做,但是你的应用服务器可能失败...的IBM WebSphere 3.5失败对我的很久以前,Tomcat会很好地传播信息;请参阅Sun论坛上的JavaServer Pages (JSP) and JSTL - Error page: preserve header "HTTP/1.x 400 My message"?。
最后我用以下解决方法,但这是一种JSP具体的,而实际上可能是老:
<%@ page isErrorPage="true" %>
<%
// This attribute is NOT set when calling HttpResponse#setStatus and then
// explicitely incuding this error page using RequestDispatcher#include()
// So: only set by HttpResponse#sendError()
Integer origStatus =
(Integer)request.getAttribute("javax.servlet.error.status_code");
if(origStatus != null) {
String origMessage =
(String)request.getAttribute("javax.servlet.error.message");
if(origMessage != null) {
response.reset();
response.setContentType("text/html");
// deprecated, but works:
response.setStatus(origStatus.intValue(), origMessage);
// would yield recursive error:
// response.sendError(origStatus, origMessage);
}
}
%>
而且如果你碰巧使用Internet Explorer测试:禁用“显示友好HTTP错误信息”。 (当不禁用IE浏览器时,IE对HTML内容的某些最小长度有一些奇怪的要求,如果不符合,将会使IE显示自己的错误消息。另请参阅微软的Description of Hypertext Transport Protocol Error Messages上的注册表项HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Main\ErrorThresholds
。)
经过澄清之后,我在Tomcat中试了这个。执行
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "message goes here");
返回
HTTP/1.1 400 message goes here
作为响应的第一行。
必须有与您正在使用的servlet容器有问题。
根据文档,sendError只保证在内容中发送消息。它没有提到任何有关状态的信息。 – 2009-07-08 23:25:03
如果您正在使用Tomcat,请参见设置org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER:
http://tomcat.apache.org/tomcat-5.5-doc/config/systemprops.html
- 如果这是真实的自定义HTTP状态消息将HTTP头中使用。用户必须确保任何此类消息均为ISO-8859-1编码,特别是在消息中包含用户提供的输入时,以防止可能存在的XSS漏洞。如果未指定,则将使用默认值false。
查看原始漏洞此页面为一些细节:
http://www.securityfocus.com/archive/1/archive/1/495021/100/0/threaded
在动力弹簧的Web应用程序,Tomcat上运行我用以下豆:
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.springframework.beans.factory.InitializingBean;
public class SystemPropertiesInitializingBean implements InitializingBean {
private Map<String, String> systemProperties;
@Override
public void afterPropertiesSet() throws Exception {
if (null == systemProperties || systemProperties.isEmpty()) {
return;
}
final Set<Entry<String, String>> entrySet = systemProperties.entrySet();
for (final Entry<String, String> entry : entrySet) {
final String key = entry.getKey();
final String value = entry.getValue();
System.setProperty(key, value);
}
}
public void setSystemProperties(final Map<String, String> systemProperties) {
this.systemProperties = systemProperties;
}
}
而在的applicationContext .XML:
<bean class="....SystemPropertiesInitializingBean">
<property name="systemProperties">
<map>
<entry key="org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER" value="true"/>
</map>
</property>
</bean>
当您使用sendError时,servlet容器返回的默认原因短语是否有问题? – laz 2009-07-08 22:49:56
它没有什么特别的错,只是我想发送一个更具体的消息。 – 2009-07-08 23:28:18