En Java, este código genera una excepción cuando el resultado HTTP es el rango 404:
URL url = new URL("http://stackoverflow.com/asdf404notfound");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getInputStream(); // throws!
En mi caso, sé que el contenido es 404, pero de todos modos me gustaría leer el cuerpo de la respuesta.
(En mi caso real, el código de respuesta es 403, pero el cuerpo de la respuesta explica el motivo del rechazo y me gustaría mostrárselo al usuario).
¿Cómo puedo acceder al cuerpo de respuesta?
java
http
httpurlconnection
Dan Fabulich
fuente
fuente
Respuestas:
Aquí está el informe de error (cerrado, no se solucionará, no es un error).
Su consejo es codificar así:
HttpURLConnection httpConn = (HttpURLConnection)_urlConnection; InputStream _is; if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) { _is = httpConn.getInputStream(); } else { /* error from server */ _is = httpConn.getErrorStream(); }
fuente
httpConn.getResponseCode() >= 400
(y su solución tiene un error, invirtiendo los flujos de entrada para usar)Es el mismo problema que estaba teniendo:
HttpUrlConnection
regresaFileNotFoundException
si intenta leergetInputStream()
desde la conexión.En su lugar, debe usar
getErrorStream()
cuando el código de estado sea superior a 400.Más que esto, tenga cuidado, ya que no solo 200 es el código de estado de éxito, incluso 201, 204, etc. se utilizan a menudo como estados de éxito.
Aquí tienes un ejemplo de cómo fui a gestionarlo.
... 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 esta manera, podrá obtener la respuesta necesaria tanto en casos de éxito como de error.
¡Espero que esto ayude!
fuente
En .Net, tiene la propiedad Response de WebException que le da acceso a la transmisión en una excepción. Así que supongo que esta es una buena forma para Java, ...
private InputStream dispatch(HttpURLConnection http) throws Exception { try { return http.getInputStream(); } catch(Exception ex) { return http.getErrorStream(); } }
O una implementación que utilicé. (Es posible que necesite cambios para la codificación u otras cosas. Funciona en el entorno actual).
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(); }
fuente
Sé que esto no responde a la pregunta directamente, pero en lugar de usar la biblioteca de conexión HTTP proporcionada por Sun, es posible que desee echar un vistazo a Commons HttpClient , que (en mi opinión) tiene una API mucho más fácil de trabajar.
fuente
Primero verifique el código de respuesta y luego use
HttpURLConnection.getErrorStream()
fuente
InputStream is = null; if (httpConn.getResponseCode() !=200) { is = httpConn.getErrorStream(); } else { /* error from server */ is = httpConn.getInputStream(); }
fuente
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
Mi código de ejecución.
HttpURLConnection httpConn = (HttpURLConnection) urlConn; if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) { in = new InputStreamReader(urlConn.getInputStream()); BufferedReader bufferedReader = new BufferedReader(in); if (bufferedReader != null) { int cp; while ((cp = bufferedReader.read()) != -1) { sb.append((char) cp); } bufferedReader.close(); } in.close(); } else { /* error from server */ in = new InputStreamReader(httpConn.getErrorStream()); BufferedReader bufferedReader = new BufferedReader(in); if (bufferedReader != null) { int cp; while ((cp = bufferedReader.read()) != -1) { sb.append((char) cp); } bufferedReader.close(); } in.close(); } System.out.println("sb="+sb);
fuente
Cómo leer el cuerpo de la respuesta 404 en java:
Use la biblioteca Apache: https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/apidocs/
o Java 11: https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html
El fragmento que se muestra a continuación usa Apache:
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.util.EntityUtils; CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse resp = client.execute(new HttpGet(domainName + "/blablablabla.html")); String response = EntityUtils.toString(resp.getEntity());
fuente