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의 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를 살펴보고 싶을 수 있습니다. Commons HttpClient 는 작업하기 훨씬 더 쉬운 API를 가지고 있습니다.
답변
먼저 응답 코드를 확인한 다음 HttpURLConnection.getErrorStream()
답변
InputStream is = null;
if (httpConn.getResponseCode() !=200) {
is = httpConn.getErrorStream();
} else {
/* error from server */
is = httpConn.getInputStream();
}
답변
내 실행 코드.
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);