Pergunta

Em Java, este código gera uma exceção quando o resultado HTTP é 404 gama:

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

No meu caso, eu descobri que o conteúdo é 404, mas eu ainda gostaria de ler o corpo da resposta de qualquer maneira.

(No meu caso real o código de resposta é 403, mas o corpo da resposta explica a razão para a rejeição, e eu gostaria de mostrar que para o usuário.)

Como posso acessar o corpo da resposta?

Foi útil?

Solução

Aqui está a relatório de bug (perto, não vai resolver, não um bug).

Seu conselho não é um código como este:

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

Outras dicas

É o mesmo problema que eu estava tendo: HttpUrlConnection retornos FileNotFoundException se você tentar ler o getInputStream() a partir da conexão.
em vez disso você deve usar getErrorStream() quando o código de status é maior do que 400.

Mais do que isso, por favor, tenha cuidado, uma vez que não é apenas de 200 para ser o código de status de sucesso, mesmo 201, 204, etc. são frequentemente utilizados como status de sucesso.

Aqui está um exemplo de como eu fui para gerenciá-lo

... 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....

Desta forma, você será capaz de obter a resposta necessária em ambos os casos de sucesso e de erro.
Espero que isso ajude!

Na Net você tem a propriedade de resposta do WebException que dá acesso ao fluxo em uma exceção. Então eu acho que essa é uma boa maneira para Java, ...

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

Ou uma implementação i usado. (Talvez seja necessário mudanças para a codificação ou outras coisas. Trabalha em ambiente atual.)

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();
}

Eu sei que isto não responde a pergunta diretamente, mas em vez de usar a biblioteca de conexões HTTP fornecido pela Sun, você pode querer dar uma olhada em Commons HttpClient , que (na minha opinião) tem uma API muito mais fácil de trabalhar com ele.

Primeiro, verifique o código de resposta e, em seguida, usar HttpURLConnection.getErrorStream()

InputStream is = null;
if (httpConn.getResponseCode() !=200) {
    is = httpConn.getErrorStream();
} else {
     /* error from server */
    is = httpConn.getInputStream();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top