Javaでは、HTTPの結果が404範囲の場合、次のコードは例外をスローします。
URL url = new URL("http://stackoverflow.com/asdf404notfound");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.getInputStream(); // throws!
私の場合、コンテンツが404であることを知っていますが、それでも応答の本文を読みたいです。
(私の実際のケースでは、応答コードは403ですが、応答の本文で拒否の理由が説明されているので、それをユーザーに表示したいと思います。)
応答本文にアクセスするにはどうすればよいですか?
バグレポートはこちらです (閉じる、修正しない、バグではない)。
彼らのアドバイスは次のようにコーディングすることです:
HttpURLConnection httpConn = (HttpURLConnection)_urlConnection;
InputStream _is;
if (httpConn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
_is = httpConn.getInputStream();
} else {
/* error from server */
_is = httpConn.getErrorStream();
}
私が抱えていたのと同じ問題です:接続からgetInputStream()
を読み取ろうとすると、HttpUrlConnection
はFileNotFoundException
を返します。
代わりに、ステータスコードが400より大きい場合はgetErrorStream()
を使用する必要があります。
さらに、成功ステータスコードは200だけではなく、201、204なども成功ステータスとして使用されることが多いため、注意してください。
ここに私がそれを管理するために行った方法の例があります
... 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....
このようにして、成功とエラーの両方のケースで必要な応答を取得できます。
お役に立てれば!
.Netには、例外にストリームへのアクセスを許可するWebExceptionのResponseプロパティがあります。だから、これはJavaにとって良い方法だと思う...
private InputStream dispatch(HttpURLConnection http) throws Exception {
try {
return http.getInputStream();
} catch(Exception ex) {
return http.getErrorStream();
}
}
または私が使用した実装。 (エンコードなどの変更が必要になる場合があります。現在の環境で動作します。)
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();
}
最初に応答コードを確認してから、HttpURLConnection.getErrorStream()
を使用します
私はこれが質問に直接答えないことを知っていますが、Sunが提供するHTTP接続ライブラリを使用する代わりに、 Commons HttpClient を見るとよいかもしれません(私の意見では)作業がはるかに簡単なAPI。
InputStream is = null;
if (httpConn.getResponseCode() !=200) {
is = httpConn.getErrorStream();
} else {
/* error from server */
is = httpConn.getInputStream();
}