จะรับเนื้อหาตอบสนองโดยใช้ HttpURLConnection ได้อย่างไรเมื่อส่งคืนรหัสอื่นที่ไม่ใช่ 2xx


102

ฉันมีปัญหาในการดึงการตอบสนอง Json ในกรณีที่เซิร์ฟเวอร์ส่งคืนข้อผิดพลาด ดูรายละเอียดด้านล่าง

ฉันดำเนินการตามคำขออย่างไร

ฉันใช้java.net.HttpURLConnection. ฉันตั้งค่าคุณสมบัติการร้องขอจากนั้นฉันทำ:

conn = (HttpURLConnection) url.openConnection();

หลังจากนั้นเมื่อคำขอสำเร็จฉันจะได้รับคำตอบ Json:

br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
sb = new StringBuilder();
String output;
while ((output = br.readLine()) != null) {
  sb.append(output);
}
return sb.toString();

... และปัญหาคือ:

ฉันไม่สามารถดึงข้อมูล Json ที่ได้รับเมื่อเซิร์ฟเวอร์ส่งคืนข้อผิดพลาดบางอย่างเช่น 50x หรือ 40x บรรทัดต่อไปนี้พ่น IOException:

br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
// throws java.io.IOException: Server returned HTTP response code: 401 for URL: www.example.com

เซิร์ฟเวอร์ส่งเนื้อหาอย่างแน่นอนฉันเห็นในเครื่องมือภายนอก Burp Suite:

HTTP/1.1 401 Unauthorized

{"type":"AuthApiException","message":"AuthApiException","errors":[{"field":"email","message":"Invalid username and/or password."}]}

ฉันสามารถรับข้อความตอบกลับ (เช่น "Internal Server Error") และรหัส (เช่น "500") โดยใช้วิธีการต่อไปนี้:

conn.getResponseMessage();
conn.getResponseCode();

แต่ฉันไม่สามารถดึงเนื้อหาคำขอได้ ... อาจจะมีวิธีการบางอย่างที่ฉันไม่ได้สังเกตเห็นในห้องสมุด?

คำตอบ:


137

หากรหัสตอบกลับไม่ใช่ 200 หรือ 2xx ให้ใช้getErrorStream()แทนgetInputStream().


3
ในกรณีของฉันมีรหัสตอบกลับ 403 getErrorStream () คืนค่า null
Sip

74

ใช้ผิดวิธีสำหรับข้อผิดพลาดนี่คือรหัสการทำงาน:

BufferedReader br = null;
if (100 <= conn.getResponseCode() && conn.getResponseCode() <= 399) {
    br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else {
    br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}

3
HttpURLConnection.getErrorStream()( sun.net.www.protocol.httpการนำไปใช้งาน) ส่งคืนnullเว้นแต่responseCode >= 400ดังนั้นเช็ค 299 ของคุณอาจไม่ถูกต้อง
vladr

6
หากคุณใช้ Java 8 คุณจะได้รับการตอบสนองเป็นสตริง String responseBody = br.lines().collect(Collectors.joining());
Lanil Marasinghe

1
ช่วงที่ถูกต้องคือ 200 ... 399 เนื่องจาก 3xx เป็นสถานะ "เปลี่ยนเส้นทาง" ไม่ใช่ข้อผิดพลาด
luca.vercelli

1
@ luca.vercelli ฉันคิดว่ามันควรจะเป็น 100..399 เพราะ 100..199 สำหรับการตอบสนอง "เชิงข้อมูล" ตามที่กำหนดไว้ในen.wikipedia.org/wiki/…
WindRider

3

นี่เป็นวิธีง่ายๆในการตอบสนองที่ประสบความสำเร็จจากเซิร์ฟเวอร์เช่น PHP echo มิฉะนั้นจะเป็นข้อความแสดงข้อผิดพลาด

BufferedReader br = null;
if (conn.getResponseCode() == 200) {
    br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String strCurrentLine;
        while ((strCurrentLine = br.readLine()) != null) {
               System.out.println(strCurrentLine);
        }
} else {
    br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
    String strCurrentLine;
        while ((strCurrentLine = br.readLine()) != null) {
               System.out.println(strCurrentLine);
        }
}

if(...)ควรตรวจสอบรหัสที่ประสบความสำเร็จมากขึ้นในความเป็นจริง 2xx ทั้งหมดไม่เพียง 200
kiedysktos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.