En Java, ce code lève une exception lorsque le résultat HTTP est 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, 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 réponse?
Voici le rapport de bug (fermer, 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();
}
C'est le même problème que j'avais: HttpUrlConnection
renvoie FileNotFoundException
si vous essayez de lire la getInputStream()
à partir de la connexion.
Vous devriez plutôt utiliser getErrorStream()
lorsque le code d'état est supérieur à 400.
Plus que cela, soyez prudent car ce n'est pas seulement 200 pour être le code d'état de réussite, même 201, 204, etc. sont souvent utilisés comme états de réussite.
Voici un exemple de la façon dont je suis allé 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 t'aides!
Dans .Net, vous avez la propriété Response de WebException qui donne accès au flux SUR une exception. Donc je suppose que c'est un bon moyen 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. (Pourrait avoir besoin de modifications 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();
}
Vérifiez d'abord le code de réponse, puis utilisez HttpURLConnection.getErrorStream()
Je sais que cela ne répond pas directement à la question, mais au lieu d'utiliser la bibliothèque de connexions HTTP fournie par Sun, vous voudrez peut-être jeter un œil à Commons HttpClient , qui (à mon avis) a un API beaucoup plus facile à utiliser.
InputStream is = null;
if (httpConn.getResponseCode() !=200) {
is = httpConn.getErrorStream();
} else {
/* error from server */
is = httpConn.getInputStream();
}