¿Cómo obtener el cuerpo de la respuesta usando HttpURLConnection, cuando se devuelve un código que no sea 2xx?

95

Tengo un problema para recuperar la respuesta de Json en caso de que el servidor devuelva un error. Vea los detalles abajo.

Cómo realizo la solicitud

Yo uso java.net.HttpURLConnection. Configuro propiedades de solicitud, luego lo hago:

conn = (HttpURLConnection) url.openConnection();

Después de eso, cuando la solicitud es exitosa, obtengo la respuesta Json:

br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
sb = new StringBuilder();
String output;
while ((output = br.readLine()) != null) {
  sb.append(output);
}
return sb.toString();

... y el problema es:

No puedo recuperar Json recibido cuando el servidor devuelve algún error como 50x o 40x. La siguiente línea arroja IOException:

br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
// throws java.io.IOException: Server returned HTTP response code: 401 for URL: www.example.com

El servidor envía el cuerpo seguro, lo veo en la herramienta externa Burp Suite:

HTTP/1.1 401 Unauthorized

{"type":"AuthApiException","message":"AuthApiException","errors":[{"field":"email","message":"Invalid username and/or password."}]}

Puedo obtener un mensaje de respuesta (es decir, "Error interno del servidor") y el código (es decir, "500") usando los siguientes métodos:

conn.getResponseMessage();
conn.getResponseCode();

Pero no puedo recuperar el cuerpo de la solicitud ... ¿tal vez hay algún método que no noté en la biblioteca?

kiedysktos
fuente

Respuestas:

132

Si el código de respuesta no es 200 o 2xx, utilícelo en getErrorStream()lugar degetInputStream().

Marqués de Lorne
fuente
2
en mi caso, teniendo un código de respuesta 403, getErrorStream () devuelve nulo
Sip
68

Para aclarar las cosas, aquí está mi código de trabajo:

if (200 <= conn.getResponseCode() && conn.getResponseCode() <= 399) {
    br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else {
    br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
kiedysktos
fuente
3
HttpURLConnection.getErrorStream()( sun.net.www.protocol.httpimplementación) devuelve a nullmenos que responseCode >= 400, por lo que su comprobación de 299 probablemente sea incorrecta.
vladr
5
Si está utilizando Java 8, puede obtener la respuesta como una cadena. String responseBody = br.lines().collect(Collectors.joining());
Lanil Marasinghe
1
El rango correcto es 200 ... 399, ya que 3xx es un estado de "redireccionamiento", no un error.
luca.vercelli
1

Esta es una manera fácil de obtener una respuesta exitosa del servidor como PHP echo de lo contrario un mensaje de error.

BufferedReader br = null;
if (conn.getResponseCode() == 200) {
    br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String strCurrentLine;
        while ((strCurrentLine = br.readLine()) != null) {
               System.out.println(strCurrentLine);
        }
} else {
    br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
    String strCurrentLine;
        while ((strCurrentLine = br.readLine()) != null) {
               System.out.println(strCurrentLine);
        }
}
Sharhabeel Hamdan
fuente