문제

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

다른 팁

내가 가진 것과 같은 문제입니다.HttpUrlConnection 보고 FileNotFoundException 당신이 읽으려고한다면 getInputStream() 연결에서.
대신 사용해야합니다 getErrorStream() 상태 코드가 400보다 높은 경우

이 이상의 경우 성공 상태 코드가 될 수있는 것은 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의 응답 속성이있어 예외적으로 스트림에 액세스 할 수 있습니다. 그래서 이것은 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