在Java中读取错误响应主体

Dan*_*ich 83 java http httpurlconnection

在Java中,当HTTP结果为404范围时,此代码抛出异常:

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

在我的情况下,我碰巧知道内容是404,但我仍然想要阅读回复的主体.

(在我的实际情况中,响应代码是403,但响应正文解释了拒绝的原因,我想将其显示给用户.)

我如何访问响应正文?

Tof*_*eer 157

这是错误报告(关闭,不会修复,不是错误).

他们的建议是这样的代码:

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

  • 像"201 CREATED"这样的其他成功代码不会在这里失败吗? (6认同)
  • 当响应代码> = 400时,您不希望获得错误流,而不是相反吗? (5认同)
  • 如果出现错误,getInputStream()将抛出IO异常.您应该捕获异常并使用getErrorStream()从错误流中读取.这似乎是比检查httpresponse代码更好的方法. (3认同)
  • 问题是,如果您读取HttpUrlConnection.getErrorStream()代码,您将看到它始终返回null.(Java 6):-( (3认同)
  • 错误报告建议检查`httpConn.getResponseCode()> = 400`(他们的解决方法有错误,翻转输入流使用) (3认同)
  • 和java 7一样. (2认同)

gpi*_*ese 13

这与我遇到的问题相同: 如果您尝试从连接中读取,则HttpUrlConnection返回. 您应该在状态代码高于400时使用.FileNotFoundExceptiongetInputStream()
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....
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您将能够在成功和错误情况下获得所需的响应.

希望这可以帮助!


Voz*_*zie 11

在.Net中,您具有WebException的Response属性,该属性允许在异常时访问流.所以我想这是一个很好的Java方式,...

private InputStream dispatch(HttpURLConnection http) throws Exception {
    try {
        return http.getInputStream();
    } catch(Exception ex) {
        return http.getErrorStream();
    }
}
Run Code Online (Sandbox Code Playgroud)

或者我使用的实现.(可能需要更改编码或其他内容.在当前环境中工作.)

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();
}
Run Code Online (Sandbox Code Playgroud)