代码之家  ›  专栏  ›  技术社区  ›  Adam Crume

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

  •  40
  • Adam Crume  · 技术社区  · 16 年前

    我正在使用Java中的REST Web服务。如果出了什么问题,我需要一种好的方法来向客户机发送错误消息。

    根据 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" .

    7 回复  |  直到 7 年前
        1
  •  20
  •   Hank Gay    16 年前

    我认为任何一个RESTful客户都不会期望看到原因短语来找出哪里出了问题;我所看到/使用的大多数RESTful服务都会在响应的主体中发送标准的状态信息和扩展的消息。 sendError(int, String) 非常适合这种情况。

        2
  •  18
  •   Nicktar Sotirios Delimanolis    7 年前

    如果您使用的是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

        3
  •  10
  •   laz    16 年前

    在你澄清之后,我在Tomcat尝试过这个。执行

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

    收益率

    HTTP/1.1 400 message goes here
    

    作为响应的第一行。

    您使用的servlet容器一定有问题。

        4
  •  2
  •   cafebabe    16 年前

    我不太熟悉休息时的“最佳实践”。但我知道这个概念是基于HTTP的,以及它应该如何自然地运行。那么,对于应用程序错误,比如“application/myapp exception”和一些“bla bla”,在正文中使用mime类型和简单文本如何?您可以为此提供客户端库。

    对于应用程序错误,我不会使用HTTP响应代码。因为我想知道失败的原因:是我的应用程序还是我的HTTP服务器。

    (我希望在这里也能看到一些最佳实践建议。)

        5
  •  0
  •   cjstehno    16 年前

    目前还不清楚你想要完成什么。我的第一个想法是发送错误,但你说这不做你想要的…您是否考虑过创建一组“错误响应”,即包含错误消息或代码以及任何其他有用信息的特定XML或JSON内容(或用作传输语言的任何内容)?

    我曾经为基于SpringMVC的RESTful服务做过类似的工作,它工作得很好,但是为了防止客户机收到一般的500条消息或其他东西,您必须捕捉并处理每个异常。Spring异常分解器为此工作得很好。

    希望这有帮助…如果不是的话,也许你会更清楚地知道你想完成什么。很抱歉,如果我有点迟钝,错过了一些明显的东西。

        6
  •  0
  •   Arjan    15 年前

    我认为 sendError 应该这样做,但您的应用程序服务器可能出现故障…IBM WebSphere 3.5很久以前在我身上失败了,而Tomcat可以很好地传播消息;请参见 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对HTML内容的某些最小长度有一些奇怪的要求,如果不满足该要求,则会使IE显示自己的错误消息。另请参见注册表项 HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Main\ErrorThresholds 在微软 Description of Hypertext Transport Protocol Error Messages )

        7
  •  0
  •   sth    15 年前

    在使用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>