Swift Alamofire: วิธีรับรหัสสถานะการตอบกลับ HTTP


106

ฉันต้องการดึงรหัสสถานะการตอบกลับ HTTP (เช่น 400, 401, 403, 503 ฯลฯ ) สำหรับคำขอที่ล้มเหลว (และเพื่อความสำเร็จด้วย) ในรหัสนี้ฉันกำลังทำการพิสูจน์ตัวตนผู้ใช้ด้วย HTTP Basic และต้องการส่งข้อความถึงผู้ใช้ว่าการรับรองความถูกต้องล้มเหลวเมื่อผู้ใช้พิมพ์รหัสผ่านผิด

Alamofire.request(.GET, "https://host.com/a/path").authenticate(user: "user", password: "typo")
    .responseString { (req, res, data, error) in
        if error != nil {
            println("STRING Error:: error:\(error)")
            println("  req:\(req)")
            println("  res:\(res)")
            println("  data:\(data)")
            return
        }
        println("SUCCESS for String")
}
    .responseJSON { (req, res, data, error) in
        if error != nil {
            println("JSON Error:: error:\(error)")
            println("  req:\(req)")
            println("  res:\(res)")
            println("  data:\(data)")
            return
        }
        println("SUCCESS for JSON")
}

ขออภัยข้อผิดพลาดที่เกิดขึ้นดูเหมือนจะไม่ได้ระบุว่าได้รับรหัสสถานะ HTTP 409 จริง:

STRING Error:: error:Optional(Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo=0x7f9beb8efce0 {NSErrorFailingURLKey=https://host.com/a/path, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://host.com/a/path})
  req:<NSMutableURLRequest: 0x7f9beb89d5e0> { URL: https://host.com/a/path }
  res:nil
  data:Optional("")
JSON Error:: error:Optional(Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo=0x7f9beb8efce0 {NSErrorFailingURLKey=https://host.com/a/path, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://host.com/a/path})
  req:<NSMutableURLRequest: 0x7f9beb89d5e0> { URL: https://host.com/a/path }
  res:nil
  data:nil

นอกจากนี้จะเป็นการดีที่จะดึงเนื้อหา HTTP เมื่อเกิดข้อผิดพลาดเนื่องจากฝั่งเซิร์ฟเวอร์ของฉันจะใส่คำอธิบายที่เป็นข้อความของข้อผิดพลาดไว้ที่นั่น

คำถาม
เป็นไปได้ไหมที่จะดึงรหัสสถานะจากการตอบกลับที่ไม่ใช่ 2xx?
เป็นไปได้หรือไม่ที่จะดึงรหัสสถานะเฉพาะเมื่อตอบกลับ 2xx?
เป็นไปได้ไหมที่จะดึงเนื้อหา HTTP จากการตอบสนองที่ไม่ใช่ 2xx

ขอบคุณ!


1
หากคุณไม่ได้รับการรับรองความถูกต้องคุณจะได้รับ -999 จากการออกแบบ ไม่แน่ใจว่าเหตุใดจึงสามารถแก้ไขได้ ... คุณแก้ปัญหานี้หรือไม่?
Guido Hendriks

คำตอบ:


188

สำหรับผู้ใช้Swift 3.x / Swift 4.0 / Swift 5.0 ที่มีAlamofire> = 4.0 / Alamofire> = 5.0


response.response?.statusCode

ตัวอย่างรายละเอียดเพิ่มเติม:

Alamofire.request(urlString)
        .responseString { response in
            print("Success: \(response.result.isSuccess)")
            print("Response String: \(response.result.value)")

            var statusCode = response.response?.statusCode
            if let error = response.result.error as? AFError {  
                statusCode = error._code // statusCode private                 
                switch error {
                case .invalidURL(let url):
                    print("Invalid URL: \(url) - \(error.localizedDescription)")
                case .parameterEncodingFailed(let reason):
                    print("Parameter encoding failed: \(error.localizedDescription)")
                    print("Failure Reason: \(reason)")
                case .multipartEncodingFailed(let reason):
                    print("Multipart encoding failed: \(error.localizedDescription)")
                    print("Failure Reason: \(reason)")
                case .responseValidationFailed(let reason):
                    print("Response validation failed: \(error.localizedDescription)")
                    print("Failure Reason: \(reason)")

                    switch reason {
                    case .dataFileNil, .dataFileReadFailed:
                        print("Downloaded file could not be read")
                    case .missingContentType(let acceptableContentTypes):
                        print("Content Type Missing: \(acceptableContentTypes)")
                    case .unacceptableContentType(let acceptableContentTypes, let responseContentType):
                        print("Response content type: \(responseContentType) was unacceptable: \(acceptableContentTypes)")
                    case .unacceptableStatusCode(let code):
                        print("Response status code was unacceptable: \(code)")
                        statusCode = code
                    }
                case .responseSerializationFailed(let reason):
                    print("Response serialization failed: \(error.localizedDescription)")
                    print("Failure Reason: \(reason)")
                    // statusCode = 3840 ???? maybe..
                default:break
                }

                print("Underlying error: \(error.underlyingError)")
            } else if let error = response.result.error as? URLError {
                print("URLError occurred: \(error)")
            } else {
                print("Unknown error: \(response.result.error)")
            }

            print(statusCode) // the status code
    } 

(Alamofire 4 มีระบบข้อผิดพลาดใหม่ทั้งหมดดูรายละเอียดที่นี่ )

สำหรับผู้ใช้Swift 2.x ที่มีAlamofire> = 3.0

Alamofire.request(.GET, urlString)
      .responseString { response in
             print("Success: \(response.result.isSuccess)")
             print("Response String: \(response.result.value)")
             if let alamoError = response.result.error {
               let alamoCode = alamoError.code
               let statusCode = (response.response?.statusCode)!
             } else { //no errors
               let statusCode = (response.response?.statusCode)! //example : 200
             }
}

response.result.error สามารถทำให้คุณมีข้อผิดพลาด Alamofire ตัวอย่างเช่น StatusCodeValidationFailed, FAILURE: Error Domain=com.alamofire.error Code=-6003. ถ้าคุณต้องการรับข้อผิดพลาดการตอบสนอง HTTP จริง ๆ จะดีกว่าสำหรับผู้ใช้response.response?.statusCode
Kostiantyn Koval

@KostiantynKoval ฉันเห็นด้วยกับคุณคุณได้ชี้แจงที่เหมาะสมแล้ว ฉันอัปเดตคำตอบเพื่อความชัดเจน
Alessandro Ornano

50

ในตัวจัดการการเสร็จสิ้นพร้อมอาร์กิวเมนต์responseด้านล่างฉันพบว่ารหัสสถานะ http อยู่ในresponse.response.statusCode:

Alamofire.request(.POST, urlString, parameters: parameters)
            .responseJSON(completionHandler: {response in
                switch(response.result) {
                case .Success(let JSON):
                    // Yeah! Hand response
                case .Failure(let error):
                   let message : String
                   if let httpStatusCode = response.response?.statusCode {
                      switch(httpStatusCode) {
                      case 400:
                          message = "Username or password not provided."
                      case 401:
                          message = "Incorrect password for user '\(name)'."
                       ...
                      }
                   } else {
                      message = error.localizedDescription
                   }
                   // display alert with error message
                 }

สวัสดี statusCode 200 จะล้มเหลวหรือไม่ คำขอของฉันได้รับการจัดการอย่างถูกต้องที่ฝั่งเซิร์ฟเวอร์ แต่การตอบกลับอยู่ภายใต้ความล้มเหลว
perwyl

1
@perwyl ฉันไม่คิดว่า 200 เป็นข้อผิดพลาด http: ดูที่stackoverflow.com/questions/27921537/…
wcochran

2
รหัสสถานะ @perwyl 200 แสดงถึงความสำเร็จหากเซิร์ฟเวอร์ของคุณส่งคืน 200 และการตอบสนองที่ระบุข้อผิดพลาด (เช่นคุณสมบัติบางอย่างเรียกว่าการเข้าถึง = เท็จ) คุณต้องจัดการสิ่งนั้นในรหัสส่วนหน้าของคุณ
Parama Dharmika

17
    Alamofire
        .request(.GET, "REQUEST_URL", parameters: parms, headers: headers)
        .validate(statusCode: 200..<300)
        .responseJSON{ response in

            switch response.result{
            case .Success:
                if let JSON = response.result.value
                {
                }
            case .Failure(let error):
    }

สิ่งนี้ช่วยกระตุ้นแนวทางปฏิบัติที่ดีที่สุดของ api
CESCO

URW :) พยายามใช้เราเตอร์สำหรับคำขอของคุณ ;)
Abo3atef

11

วิธีที่ดีที่สุดในการรับรหัสสถานะโดยใช้ alamofire

 Alamofire.request (URL) .responseJSON {
  ตอบกลับใน

  ให้ status = response.response? .statusCode
  พิมพ์ ("STATUS \ (สถานะ)")

}

4

ในการresponseJSONทำเสร็จคุณจะได้รับรหัสสถานะจากวัตถุตอบกลับซึ่งมีประเภทNSHTTPURLResponse?:

if let response = res {
    var statusCode = response.statusCode
}

สิ่งนี้จะใช้ได้ไม่ว่ารหัสสถานะจะอยู่ในช่วงข้อผิดพลาดหรือไม่ สำหรับข้อมูลเพิ่มเติมโปรดดูเอกสาร NSHTTPURLResponseเอกสาร

สำหรับคำถามอื่นของคุณคุณสามารถใช้responseStringฟังก์ชันเพื่อรับเนื้อหาตอบกลับดิบ คุณสามารถเพิ่มสิ่งนี้นอกเหนือจากresponseJSONและทั้งสองจะถูกเรียก

.responseJson { (req, res, json, error) in
   // existing code
}
.responseString { (_, _, body, _) in
   // body is a String? containing the response body
}

3

ข้อผิดพลาดของคุณบ่งชี้ว่าการดำเนินการกำลังถูกยกเลิกด้วยเหตุผลบางประการ ฉันต้องการรายละเอียดเพิ่มเติมเพื่อทำความเข้าใจว่าทำไม แต่ผมคิดว่าปัญหาที่ใหญ่กว่าอาจเป็นได้ว่าตั้งแต่ปลายทางของปลอมไม่มีตอบกลับของเซิร์ฟเวอร์ที่แท้จริงในการรายงานและด้วยเหตุนี้คุณกำลังเห็นhttps://host.com/a/pathnil

หากคุณพบจุดสิ้นสุดที่ถูกต้องซึ่งแสดงการตอบสนองที่เหมาะสมคุณควรเห็นค่าที่ไม่ใช่ศูนย์สำหรับres(โดยใช้เทคนิคที่แซมกล่าวถึง) ในรูปแบบของNSURLHTTPResponseวัตถุที่มีคุณสมบัติเช่นstatusCodeฯลฯ

นอกจากนี้เพียงเพื่อให้มีความชัดเจนเป็นประเภทerror NSErrorจะบอกคุณว่าทำไมคำขอเครือข่ายจึงล้มเหลว รหัสสถานะของความล้มเหลวทางฝั่งเซิร์ฟเวอร์เป็นส่วนหนึ่งของการตอบสนอง

หวังว่าจะช่วยตอบคำถามหลักของคุณ


จับได้ดีฉันจดจ่ออยู่กับรายการคำถามที่ด้านล่างมากเกินไป
แซม

1
จริงๆแล้วมันได้รับรหัส 401 ไม่ได้รับอนุญาตเพราะฉันตั้งใจส่งรหัสผ่านผิดเพื่อจำลองผู้ใช้พิมพ์รหัสผ่านผิดเพื่อที่ฉันจะได้จับกรณีนั้นและให้ข้อเสนอแนะแก่ผู้ใช้ นั่นไม่ใช่ URL จริงที่ฉันใช้ แต่ฉันใช้ URL ที่ถูกต้องซึ่งส่งผลให้ประสบความสำเร็จเมื่อฉันส่งรหัสผ่านที่ถูกต้อง เอาต์พุตคอนโซลในโพสต์ต้นฉบับของฉันเป็นผลลัพธ์จริงจากการกดปุ่ม URL จริง (ยกเว้นว่า URL นั้นเป็นของปลอม) และคุณจะเห็นว่าresวัตถุนั้นเป็นnilดังนั้นคำตอบนี้ไม่สามารถช่วยได้ขออภัย
GregT

ขอบคุณสำหรับความกระจ่าง สิ่งเดียวที่สงสัยในที่นี้คือข้อผิดพลาด -999 ที่ฉันไม่พบ แต่เอกสารแสดงให้เห็นว่าคำขอกำลังถูกยกเลิก (ดังนั้นคำถามที่ว่าแม้จะได้รับคำตอบก็ควรจะสงสัย) คุณได้พยายามพิมพ์วัตถุตอบกลับสำหรับข้อผิดพลาดประเภทอื่นที่ไม่เกี่ยวข้องกับการตรวจสอบสิทธิ์หรือไม่? แค่สงสัย.
rainypixels

อ่าฉันคิดว่าerrorหมายถึงการตอบกลับด้วยรหัสสถานะที่อยู่นอกช่วงที่เราให้validate()ไว้ ขอบคุณ !!!
Gerald

3

หรือใช้การจับคู่รูปแบบ

if let error = response.result.error as? AFError {
   if case .responseValidationFailed(.unacceptableStatusCode(let code)) = error {
       print(code)
   }
}

ทำงานอย่างมีเสน่ห์
alasker

3

คุณสามารถตรวจสอบรหัสต่อไปนี้สำหรับตัวจัดการรหัสสถานะโดย alamofire

    let request = URLRequest(url: URL(string:"url string")!)    
    Alamofire.request(request).validate(statusCode: 200..<300).responseJSON { (response) in
        switch response.result {
        case .success(let data as [String:Any]):
            completion(true,data)
        case .failure(let err):
            print(err.localizedDescription)
            completion(false,err)
        default:
            completion(false,nil)
        }
    }

หากรหัสสถานะไม่ได้รับการตรวจสอบจะถูกป้อนล้มเหลวในกรณีสวิตช์


1

สำหรับผู้ใช้ Swift 2.0 ที่มี Alamofire> 2.0

Alamofire.request(.GET, url)
  .responseString { _, response, result in
    if response?.statusCode == 200{
      //Do something with result
    }
}

1

ฉันต้องการทราบวิธีรับหมายเลขรหัสข้อผิดพลาดจริง

ฉันรับช่วงโปรเจ็กต์จากคนอื่นและฉันต้องได้รับรหัสข้อผิดพลาดจาก.catchประโยคที่พวกเขาเคยตั้งค่าไว้สำหรับ Alamofire:

} .catch { (error) in

    guard let error = error as? AFError else { return }
    guard let statusCode = error.responseCode else { return }

    print("Alamofire statusCode num is: ", statusCode)
}

หรือหากต้องการรับจากresponseค่าให้ทำตามคำตอบของ @ mbryzinski

Alamofire ... { (response) in

    guard let error = response.result.error as? AFError else { return }
    guard let statusCode = error.responseCode else { return }

    print("Alamofire statusCode num is: ", statusCode)
})
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.