質問

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

これは質問に直接答えないことはわかっていますが、Sunが提供するHTTP接続ライブラリを使用する代わりに、 Commons HttpClient 。(私の意見では)はるかに使いやすいAPIを備えています。

最初に応答コードを確認してから、 HttpURLConnection.getErrorStream()

を使用します
InputStream is = null;
if (httpConn.getResponseCode() !=200) {
    is = httpConn.getErrorStream();
} else {
     /* error from server */
    is = httpConn.getInputStream();
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top