2008-10-09 9 views
1

(Voir la question connexe: How do I report an error midway through a chunked http repsonse without closing the connection?)Comment puis-je signaler une erreur à mi-chemin d'une réponse http chunked si je souhaite fermer la connexion?

Dans mon cas, la première chose à faire est que le navigateur affiche un message d'erreur. Peu importe comment non informatif.

La fermeture du ServletResponse outputStream ne fonctionne évidemment pas. Je ne lance pas d'exception, même si je ne ferme pas en premier (testé sur Tomcat 6.0.16). Je pense que ce que je veux, c'est soit un paquet RST, FIN au milieu d'un morceau, ou des en-têtes de morceaux mal formés. Après cela, je peux m'inquiéter de la façon dont les différents navigateurs réagissent.

Edité pour clarification: Ceci est pour un téléchargement de fichier, peut-être plusieurs gigaoctets de données binaires. Je ne peux pas m'assurer que toutes les données peuvent être lues ou décryptées avec succès avant que je doive commencer à en envoyer une partie.

Répondre

1

Ma propre réponse, après recherche. Première partie: Il semble qu'il n'y ait aucun moyen de convaincre les serveurs d'applications que j'ai testés de mettre une erreur sur le fil après la phase "validée". Le code Servlet suivant entraîne des en-têtes de transfert HTTP Chunked légaux sur le socket. Fait intéressant, dans le cas de WebSphere, un message d'erreur est ajouté à la fin du flux avant la marque de fin.

public class Servlet extends HttpServlet { 
    public static final int ARRAY_SIZE = 65536; 
    private static final int SEND_COUNT = 100000; 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { 

     String testData = "This is a fairly long piece of test text, running on and on and on, over and over."; 

     final ServletOutputStream outputStream = response.getOutputStream(); 
     for (int i = 0; i < SEND_COUNT; ++i) { 
      outputStream.println(testData); 
     } 
     throw new ServletException("Break it now"); 
    } 
} 

Deuxième partie: Même si le serveur d'application était prêt à écrire soit des données fausses sur le fil ou fermer la prise sans un morceau zéro longueur fermeture, les clients communs ne signalent pas une erreur. IE7, FF3 et cURL ne signalent pas les erreurs dans l'encodage des segments. Cela rend les téléchargements HTTP intrinsèquement non fiables, et est contraire à l'esprit sinon à la lettre du RFC HTTP 1.1.

0

Je pense que vous allez dans le mauvais sens. Il semble qu'il serait plus simple de ne pas commencer à envoyer les données tant que vous n'êtes pas sûr que ce sera un succès ou un échec. De cette façon, vous pouvez envoyer un message d'erreur au début si nécessaire, au lieu d'envoyer des données partielles qui ne sont pas valides.

Si vous devez vraiment, vous pourriez être en mesure d'arranger quelque chose avec JavaScript. Lorsque vous arrivez à l'erreur, quelque chose de sortie comme celui-ci avant de fermer la connexion:

<script type="text/javascript"> alert("Processing failed!"); </script> 

Vous pouvez développer le script, mais vous avez l'idée générale. Cela suppose que ce qui est renvoyé au navigateur est une page HTML, vous ne l'avez pas spécifié dans la question.

0

L'API servlet ne le permet pas. Une fois la réponse validée, le code de réponse a été envoyé. Le mieux que vous puissiez faire est de fermer la connexion et de consigner l'erreur.

+0

Citation? Où la définition de l'API Servlet indique-t-elle ce que le conteneur doit faire lorsque ma servlet lance SomeGenericError après le point de validation? Je comprends qu'il ne peut pas changer le code de réponse HTTP qui est déjà sur le fil, mais pourquoi devrait-il écrire un morceau de longueur nulle avant la fermeture. – Darron

+0

Désolé, je ne voulais pas dire que la spécification interdit le comportement que vous voulez, simplement qu'il n'y a aucun moyen de l'atteindre avec les méthodes disponibles dans la version actuelle de l'API. – johnstok

Questions connexes