W Javie ten kod zgłasza wyjątek, gdy wynik HTTP to zakres 404:
URL url = new URL("http://stackoverflow.com/asdf404notfound");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getInputStream(); // throws!
W moim przypadku tak się składa, że wiem, że treść to 404, ale i tak chciałbym przeczytać treść odpowiedzi.
(W moim przypadku kod odpowiedzi to 403, ale treść odpowiedzi wyjaśnia powód odrzucenia i chciałbym wyświetlić to użytkownikowi).
Jak mogę uzyskać dostęp do treści odpowiedzi?
java
http
httpurlconnection
Dan Fabulich
źródło
źródło
Odpowiedzi:
Oto raport o błędzie (zamknij, nie naprawi, nie jest to błąd).
Ich rada to kodowanie w ten sposób:
HttpURLConnection httpConn = (HttpURLConnection)_urlConnection; InputStream _is; if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) { _is = httpConn.getInputStream(); } else { /* error from server */ _is = httpConn.getErrorStream(); }
źródło
httpConn.getResponseCode() >= 400
(i ich obejścia zawiera błąd, odchylając inputstreams do użytku)To ten sam problem, który miałem:
HttpUrlConnection
zwraca,FileNotFoundException
jeśli spróbujesz odczytaćgetInputStream()
z połączenia.Zamiast tego należy używać,
getErrorStream()
gdy kod statusu jest wyższy niż 400.Co więcej, bądź ostrożny, ponieważ kod statusu sukcesu to nie tylko 200, nawet 201, 204 itd. Są często używane jako statusy sukcesu.
Oto przykład tego, jak sobie z tym poradziłem
... 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....
W ten sposób będziesz w stanie uzyskać potrzebną odpowiedź zarówno w przypadku powodzenia, jak i błędów.
Mam nadzieję że to pomoże!
źródło
W .Net masz właściwość Response z WebException, która daje dostęp do strumienia ON jako wyjątek. Więc myślę, że to dobry sposób na Javę, ...
private InputStream dispatch(HttpURLConnection http) throws Exception { try { return http.getInputStream(); } catch(Exception ex) { return http.getErrorStream(); } }
Albo implementacja, której użyłem. (Może wymagać zmian w kodowaniu lub innych rzeczach. Działa w obecnym środowisku).
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(); }
źródło
Wiem, że to nie odpowiada bezpośrednio na pytanie, ale zamiast korzystać z biblioteki połączeń HTTP dostarczonej przez Sun, możesz rzucić okiem na Commons HttpClient , który (moim zdaniem) ma znacznie łatwiejszy interfejs API.
źródło
Najpierw sprawdź kod odpowiedzi, a następnie użyj
HttpURLConnection.getErrorStream()
źródło
InputStream is = null; if (httpConn.getResponseCode() !=200) { is = httpConn.getErrorStream(); } else { /* error from server */ is = httpConn.getInputStream(); }
źródło
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
Mój działający kod.
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);
źródło
Jak czytać treść odpowiedzi 404 w java:
Użyj biblioteki Apache - https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/apidocs/
lub Java 11 - https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html
Podany poniżej fragment korzysta z 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());
źródło