web-dev-qa-db-fra.com

Désactiver tout le contenu de réponse d'erreur HTTP par défaut dans Tomcat

Par défaut, Tomcat renvoie du contenu HTML au client s'il rencontre un type de HTTP 404. Je sais que, par web.xml, un <error-page>peut être configuré pour personnaliser ce contenu.

Cependant, je voudrais juste que Tomcat envoie n'envoie rien en termes de contenu de la réponse (j'aimerais quand même le code d'état, bien sûr). Est-il possible de configurer facilement cela?

J'essaie d'éviter A) d'envoyer explicitement le contenu vide sur le flux de réponses à partir de mon servlet et B) de configurer des pages d'erreur personnalisées pour de nombreux états d'erreur HTTP dans mon web.xml.

Pour le contexte, je développe une API HTTP et contrôle mon propre contenu de réponse. Ainsi, pour un HTTP 500, par exemple, je renseigne du contenu XML sur la réponse contenant des informations d'erreur. Dans des situations comme HTTP 404, l'état de la réponse HTTP est suffisant pour les clients et le contenu envoyé par Tomcat n'est pas nécessaire. S'il y a une approche différente, je suis ouvert à l'entendre.

Edit: Après une enquête continue, je ne trouve toujours pas beaucoup de solutions. Si quelqu'un peut dire de façon définitive que ce n'est pas possible, ou fournir une ressource avec la preuve que cela ne fonctionnera pas, j'accepterai cela comme une réponse et j'essaierai de contourner le problème.

65
Rob Hruska

Si vous ne souhaitez pas que Tomcat affiche une page d'erreur, n'utilisez pas sendError (...). Utilisez plutôt setStatus (...). 

par exemple. si vous voulez donner une réponse 405, alors vous faites

response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);      
response.getWriter().println("The method " + request.getMethod() + 
   " is not supported by this service.");

Rappelez-vous également de ne pas lancer d'exceptions de votre servlet. À la place, attrapez l'exception et, encore une fois, définissez le code d'état vous-même.

c'est à dire.

protected void service(HttpServletRequest request,
      HttpServletResponse response) throws IOException {
  try {

    // servlet code here, e.g. super.service(request, response);

  } catch (Exception e) {
    // log the error with a timestamp, show the timestamp to the user
    long now = System.currentTimeMillis();
    log("Exception " + now, e);
    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    response.getWriter().println("Guru meditation: " + now);
  }
}

bien sûr, si vous ne voulez pas de contenu, alors n'écrivez rien pour l'auteur, mais définissez le statut.

43
Heikki Vesalainen

Bien que cela ne réponde pas exactement à la déclaration "ne rien envoyer" sur la question et sur la vague de réponse de Clive Evans , j'ai découvert que dans Tomcat, vous pouvez faire disparaître ces textes trop verbeux pages d'erreur sans créer un ErrorReportValve personnalisé.

Vous pouvez y parvenir en personnalisant ErrorReportValve à l’aide des 2 paramètres "showReport" et "showServerInfo" sur votre "server.xml":

<Valve className="org.Apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />

Lien vers la documentation officielle .

Travaillé pour moi sur Tomcat 7.0.55, ne fonctionnait pas pour moi sur Tomcat 7.0.47 (je pense que quelque chose a été rapporté sur le lien suivant http://www.mail-archive.com/[email protected] .org/msg113856.html )

36
reallynice

Le moyen rapide, légèrement sale, mais facile d'empêcher Tomcat d'envoyer un corps d'erreur consiste à appeler setErrorReportValveClass contre l'hôte Tomcat, avec une vanne de rapport d'erreur personnalisée qui remplace le rapport sans rien faire. c'est à dire:

public class SecureErrorReportValve extends ErrorReportValve {

@Override
protected void report(Request request,Response response,Throwable throwable) {
}

}

et le régler avec:

  ((StandardHost) Tomcat.getHost()).setErrorReportValveClass(yourErrorValveClassName);

Si vous souhaitez envoyer votre message et que vous pensez que Tomcat ne devrait pas y toucher, vous voulez quelque chose comme:

@Override
protected void report(final Request request, final Response response, final Throwable throwable) {
    String message = response.getMessage();
    if (message != null) {
        try {
            response.getWriter().print(message);
            response.finishResponse();
        } catch (IOException e) {
        }
    }
}
10
Clive Evans

Comme Heikki l'a dit, définir le statut à la place de sendError() empêche Tomcat de toucher l'entité/le corps/la charge de la réponse.

Si vous souhaitez uniquement envoyer les en-têtes de réponse sans aucune entité, comme dans mon cas,

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);

fait le tour. Avec Content-Length: 0, la print() n'aura aucun effet, même si elle est utilisée, comme:

response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentLength(0);
response.getWriter().print("this string will be ignored due to the above line");

le client reçoit quelque chose comme:

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 0
Date: Wed, 28 Sep 2011 08:59:49 GMT

Si vous souhaitez envoyer un message d'erreur, utilisez la fonction setContentLength() avec la longueur du message (autre que zéro) ou vous pouvez le laisser au serveur.

9
manikanta

Bien que ce soit conforme aux spécifications Servlet, pour des raisons de sécurité, je ne souhaite pas que Tomcat ou tout autre conteneur Servlet envoie les détails de l'erreur. J'ai eu quelques difficultés avec ça aussi. Après avoir cherché et essayé, la solution peut être résumée comme suit:

  1. comme mentionné, n'utilisez pas sendError(), utilisez plutôt setStatus() 
  2. des cadres comme par exemple Spring Security utilise sendError() quoique ... 
  3. écrire une Filter that
    une. redirige les appels vers sendError() vers setStatus()
    b. efface la réponse à la fin pour empêcher le conteneur de modifier davantage la réponse 

Un petit exemple de filtre de servlet faisant cela peut être trouvé ici .

6
Erich Eichinger

Pourquoi ne pas simplement configurer l'élément <error-page> avec une page HTML vide?

2
matt b

Bien que cette question soit un peu ancienne, j'ai également rencontré ce problème. Tout d'abord, le comportement de Tomcat est absolument correct. C'est par Spéc Servlet. Il ne faut pas modifier le comportement de Tomcat par rapport à la spécification. Comme Heikki Vesalainen et mrCoder l'ont mentionné, utilisez setStatus et setStatus uniquement.

Pour qui de droit, j'ai soulevé un ticket avec Tomcat pour améliorer les docs de sendError.

1
Michael-O

Configurer <error-page> Eléments dans web.xml

Éditez $CATALINA_HOME/conf/web.xml, ajoutez à la fin le <error-page> suivant, enregistrez et redémarrez Tomcat.

<web-app>

...
...
...

    <error-page>
        <error-code>404</error-code>
        <location>/404.html</location>
    </error-page>

    <error-page>
        <error-code>500</error-code>
        <location>/500.html</location>
    </error-page>

    <error-page>
        <error-code>400</error-code>
        <location>/400.html</location>
    </error-page>

</web-app>
  • Cela fonctionne très bien, même si je n'ai pas créé d'itinéraires valides pour les valeurs location spécifiées (par exemple /400.html

avant

 enter image description here

après

 enter image description here

0
Jossef Harush