web-dev-qa-db-fra.com

Comment envoyer correctement un message HTTP au client

Je travaille sur un service Web RESTful en Java. J'ai besoin d'un bon moyen d'envoyer des messages d'erreur au client si quelque chose ne va pas.

Selon le Javadoc , HttpServletResponse.setStatus(int status, String message) est obsolète "en raison de la signification ambiguë du paramètre de message."

Existe-t-il un moyen préféré de définir le message d'état ou " phrase de raison " de la réponse? La méthode sendError(int, String) ne le fait pas.

EDIT: pour clarifier, je souhaite modifier la ligne d'état HTTP, c'est-à-dire "HTTP/1.1 404 Not Found", pas le contenu du corps. Plus précisément, j'aimerais envoyer des réponses comme "HTTP/1.1 400 Missing customerNumber parameter".

40
Adam Crume

Je ne pense pas qu'un client RESTful s'attendrait à regarder la phrase de raison pour comprendre ce qui a mal tourné; la plupart des services RESTful que j'ai vus/utilisés enverront les informations d'état standard et un message étendu dans le corps de la réponse. sendError(int, String) est idéal pour cette situation.

21
Hank Gay

Si vous utilisez Tomcat, consultez le paramètre org.Apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER:

http://Tomcat.Apache.org/Tomcat-5.5-doc/config/systemprops.html

  • Si c'est vrai, des messages d'état HTTP personnalisés seront utilisés dans les en-têtes HTTP. Les utilisateurs doivent s'assurer qu'un tel message est codé ISO-8859-1, en particulier si une entrée fournie par l'utilisateur est incluse dans le message, pour éviter une éventuelle vulnérabilité XSS. S'il n'est pas spécifié, la valeur par défaut false sera utilisée.

Voir cette page pour quelques détails sur la vulnérabilité d'origine:

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

18
ars

Après votre clarification, j'ai essayé ceci dans Tomcat. Exécution

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

retour

HTTP/1.1 400 message goes here

comme première ligne de la réponse.

Il doit y avoir un problème avec le conteneur de servlet que vous utilisez.

12
laz

Je ne connais pas très bien les "meilleures pratiques" autour de REST. Mais je sais que le concept est basé sur HTTP et comment il est censé fonctionner naturellement. Alors, que diriez-vous d'utiliser un type MIME et un texte simple à l'intérieur du corps pour une erreur d'application, comme "application/myapp-exception" et certains "Bla bla"? Vous pouvez fournir une bibliothèque client pour cela.

Je n'utiliserais pas de codes de réponse HTTP pour les erreurs d'application. Parce que j'aime savoir ce qui échoue: que ce soit mon application ou mon serveur HTTP.

(J'espère que je verrai ici aussi quelques conseils sur les meilleures pratiques.)

2
cafebabe

Dans l'application Web propulsée par Spring, fonctionnant sur Tomcat, j'utilise le bean suivant:

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;
    }

}

Et dans 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>
0
Illarion Kovalchuk

Ce que vous essayez d'accomplir n'est pas vraiment clair. Ma première pensée a été le sendError mais vous dites que cela ne fait pas ce que vous voulez ... contient le message d'erreur ou le code et toute autre information utile?

J'ai fait quelque chose comme ça pour les services RESTful basés sur Spring-mvc il y a quelque temps et cela a bien fonctionné, mais vous devez à peu près intercepter et gérer chaque exception pour empêcher le client d'obtenir un message générique 500 ou quelque chose. Les résolveurs des exceptions de printemps ont bien fonctionné pour cela.

J'espère que cela vous aidera ... sinon, peut-être un peu plus de clarté sur ce que vous essayez d'accomplir. Désolé si je suis dense et que je manque quelque chose d'évident.

0
cjstehno

Je pense que le sendError devrait le faire, mais votre serveur d'applications peut échouer ... IBM WebSphere 3.5 a échoué il y a longtemps alors que Tomcat propagerait très bien le message; voir JavaServer Pages (JSP) et JSTL - Page d'erreur: conserver l'en-tête "HTTP/1.x 400 My message"? sur les forums Sun.

Finalement, j'ai utilisé la solution de contournement suivante, mais c'est une sorte de JSP spécifique, et peut en fait être ancien:

<%@ 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); 
        }
    }
%>

Et s'il vous arrive de tester avec Internet Explorer: désactivez "Afficher les messages d'erreur HTTP conviviaux". (Lorsqu'il ne le désactive pas, IE a une exigence étrange d'une longueur minimale du contenu HTML qui, s'il n'est pas satisfait, ferait - ou fera - IE afficher son propre message d'erreur à la place. Voir aussi la clé de registre HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Main\ErrorThresholds chez Microsoft Description des messages d'erreur du protocole de transport hypertexte .)

0
Arjan