101 votes

Lire le corps de la réponse à une erreur en Java

En Java, ce code lève une exception lorsque le résultat HTTP est de l'ordre de 404 :

URL url = new URL("http://stackoverflow.com/asdf404notfound");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getInputStream(); // throws!

Dans mon cas, je sais que le contenu est 404, mais j'aimerais quand même lire le corps de la réponse.

(Dans mon cas réel, le code de réponse est 403, mais le corps de la réponse explique la raison du rejet, et j'aimerais l'afficher à l'utilisateur).

Comment puis-je accéder au corps de la réponse ?

187voto

TofuBeer Points 32441

Voici le rapport de bogue (fermé, ne sera pas corrigé, pas un bug).

Leur conseil est de coder comme ceci :

HttpURLConnection httpConn = (HttpURLConnection)_urlConnection;
InputStream _is;
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
    _is = httpConn.getInputStream();
} else {
     /* error from server */
    _is = httpConn.getErrorStream();
}

17voto

gpiazzese Points 415

C'est le même problème que j'avais : HttpUrlConnection renvoie à FileNotFoundException si vous essayez de lire le getInputStream() de la connexion.
Vous devriez plutôt utiliser getErrorStream() lorsque le code d'état est supérieur à 400.

En outre, faites attention car le code d'état de réussite n'est pas seulement 200, même 201, 204, etc. sont souvent utilisés comme états de réussite.

Voici un exemple de la manière dont j'ai procédé pour le gérer

... connection code code code ...

// Get the response code 
int statusCode = connection.getResponseCode();

InputStream is = null;

if (statusCode >= 200 && statusCode < 400) {
   // Create an InputStream in order to extract the response object
   is = connection.getInputStream();
}
else {
   is = connection.getErrorStream();
}

... callback/response to your handler....

De cette façon, vous pourrez obtenir la réponse nécessaire dans les cas de réussite et d'erreur.

J'espère que cela vous aidera !

14voto

Vozzie Points 11

En .Net, vous avez la propriété Response de la WebException qui donne accès au flux ON d'une exception. Je suppose donc que c'est une bonne méthode pour Java,...

private InputStream dispatch(HttpURLConnection http) throws Exception {
    try {
        return http.getInputStream();
    } catch(Exception ex) {
        return http.getErrorStream();
    }
}

Ou une implémentation que j'ai utilisée. (Des changements peuvent être nécessaires pour l'encodage ou d'autres choses. Fonctionne dans l'environnement actuel).

private String dispatch(HttpURLConnection http) throws Exception {
    try {
        return readStream(http.getInputStream());
    } catch(Exception ex) {
        readAndThrowError(http);
        return null; // <- never gets here, previous statement throws an error
    }
}

private void readAndThrowError(HttpURLConnection http) throws Exception {
    if (http.getContentLengthLong() > 0 && http.getContentType().contains("application/json")) {
        String json = this.readStream(http.getErrorStream());
        Object oson = this.mapper.readValue(json, Object.class);
        json = this.mapper.writer().withDefaultPrettyPrinter().writeValueAsString(oson);
        throw new IllegalStateException(http.getResponseCode() + " " + http.getResponseMessage() + "\n" + json);
    } else {
        throw new IllegalStateException(http.getResponseCode() + " " + http.getResponseMessage());
    }
}

private String readStream(InputStream stream) throws Exception {
    StringBuilder builder = new StringBuilder();
    try (BufferedReader in = new BufferedReader(new InputStreamReader(stream))) {
        String line;
        while ((line = in.readLine()) != null) {
            builder.append(line); // + "\r\n"(no need, json has no line breaks!)
        }
        in.close();
    }
    System.out.println("JSON: " + builder.toString());
    return builder.toString();
}

2voto

matt b Points 73770

Je sais que cela ne répond pas directement à la question, mais au lieu d'utiliser la bibliothèque de connexion HTTP fournie par Sun, vous pouvez jeter un coup d'oeil à Commons HttpClient qui (à mon avis) a une API beaucoup plus facile à utiliser.

2voto

Chris Dolan Points 5435

Vérifiez d'abord le code de réponse, puis utilisez HttpURLConnection.getErrorStream()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X