Domanda

In Java, questo codice genera un'eccezione quando il risultato HTTP è un intervallo 404:

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

Nel mio caso, mi capita di sapere che il contenuto è 404, ma mi piacerebbe comunque leggere comunque il corpo della risposta.

(Nel mio caso il codice di risposta è 403, ma il corpo della risposta spiega il motivo del rifiuto e vorrei mostrarlo all'utente.)

Come posso accedere al corpo della risposta?

È stato utile?

Soluzione

Ecco la segnalazione di bug (chiudi, non risolverà, non un bug).

Il loro consiglio è di codificare in questo modo:

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

Altri suggerimenti

È lo stesso problema che stavo riscontrando: HttpUrlConnection restituisce FileNotFoundException se si tenta di leggere getInputStream () dalla connessione.
Dovresti invece usare getErrorStream () quando il codice di stato è superiore a 400.

Oltre a questo, si prega di fare attenzione poiché non è solo 200 ad essere il codice dello stato di successo, anche 201, 204, ecc. vengono spesso utilizzati come stati di successo.

Ecco un esempio di come sono andato a gestirlo

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

In questo modo, sarai in grado di ottenere la risposta necessaria in entrambi i casi di successo ed errore.
Spero che questo aiuti!

In .Net hai la proprietà Response di WebException che dà accesso al flusso su un'eccezione. Quindi immagino sia un buon modo per Java, ...

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

O un'implementazione che ho usato. (Potrebbe essere necessario apportare modifiche per la codifica o altro. Funziona nell'ambiente attuale.)

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

So che questo non risponde direttamente alla domanda, ma invece di utilizzare la libreria di connessione HTTP fornita da Sun, potresti dare un'occhiata a Commons HttpClient , che (a mio avviso) ha un'API molto più semplice con cui lavorare.

Prima controlla il codice di risposta e poi usa HttpURLConnection.getErrorStream()

InputStream is = null;
if (httpConn.getResponseCode() !=200) {
    is = httpConn.getErrorStream();
} else {
     /* error from server */
    is = httpConn.getInputStream();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top