如何正确地向客户端发送HTTP消息

我正在研究Java中的REST风格的Web服务。 如果出现错误,我需要一个很好的方法来向客户端发送错误消息。

根据Javadoc , HttpServletResponse.setStatus(int status, String message) 由于消息参数含义模糊而被弃用

有没有一个首选的方法来设置响应的状态消息或“ 原因词组 ”? sendError(int, String)方法不会这样做。

编辑:澄清,我想修改HTTP状态行,即"HTTP/1.1 404 Not Found" ,而不是正文内容。 具体来说,我想发送"HTTP/1.1 400 Missing customerNumber parameter"

我不认为任何一个RESTful客户会期望看看原因是为了弄清楚哪里出了问题; 我见过/使用过的大多数RESTful服务都会在响应的主体中发送标准的状态信息和扩展的消息。 sendError(int, String)对于这种情况是理想的。

如果您使用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编码的,特别是如果消息中包含用户提供的input,以防止可能的XSS漏洞。 如果未指定,则将使用默认值false。

有关原始漏洞的详细信息,请参阅此页面:

http://www.securityfocus.com/archive/1/archive/1/495021/100/0/threaded

澄清之后,我在Tomcat中试了一下。 执行

 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "message goes here"); 

回报

 HTTP/1.1 400 message goes here 

作为回应的第一行。

您正在使用的servlet容器必须有问题。

我不太了解REST的“最佳实践”。 但是我知道这个概念是基于HTTP的,应该如何自然地实现。 那么如何在应用程序错误中使用MIMEtypes和简单的文本内容,比如“application / myapp-exception”和一些“Bla bla”呢? 你可以提供一个客户端库。

我不会使用HTTP响应代码来处理应用程序错误。 因为我想知道什么是失败的:无论是我的应用程序还是我的HTTP服务器。

(我希望,我也会在这里看到一些最佳实践的build议。)

目前还不清楚你想要完成什么。 我的第一个想法是sendError,但你说没有做你想做的事情…你有没有看过创build一组“错误响应”,这意味着特定的XML或JSON内容(或任何你用作传输语言)包含错误消息或代码和其他有用的信息?

我为Spring-mvc基于RESTful的服务做了类似的事情,它运行良好,但是你必须捕获和处理每一个exception,以防止客户端得到一个通用的500消息。 Spring Exception Resolvers为此工作得很好。

希望这有助于…如果没有,也许更清楚你想要完成什么。 对不起,如果我正在密集和缺less明显的东西。

我认为sendError应该这样做,但是你的应用程序服务器可能会失败…很久以前,IBM WebSphere 3.5失败了,而Tomcat会传播这个消息, 请参阅JavaServer Pages(JSP)和JSTL – 错误页面:保留标题“HTTP / 1.x 400 My message”? 在Sun论坛上。

最终我使用了下面的解决方法,但这是一种特定于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进行testing:禁用“显示友好的HTTP错误消息”。 (当不禁用时,IE浏览器对HTML内容的某些最小长度有一些奇怪的要求,如果不符合,将会使IE显示自己的错误信息。另请参阅registry项HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Main\ErrorThresholds Microsoft的超文本传输​​协议错误消息说明 HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Main\ErrorThresholds 。)

在Spring动力Web应用程序中,运行在Tomcat上我使用下面的bean:

 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>