Swift Alamofire: Cách lấy mã trạng thái phản hồi HTTP


106

Tôi muốn truy xuất mã trạng thái phản hồi HTTP (ví dụ: 400, 401, 403, 503, v.v.) cho các yêu cầu không thành công (và lý tưởng cho cả thành công). Trong mã này, tôi đang thực hiện xác thực người dùng với HTTP Basic và muốn có thể thông báo cho người dùng rằng xác thực không thành công khi người dùng nhập sai mật khẩu của họ.

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")
}

Thật không may, lỗi được tạo ra dường như không cho thấy rằng mã trạng thái HTTP 409 thực sự đã được nhận:

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

Ngoài ra, sẽ rất tuyệt khi truy xuất phần thân HTTP khi xảy ra lỗi vì phía máy chủ của tôi sẽ đặt một mô tả nguyên bản về lỗi ở đó.

Câu hỏi
Có thể truy xuất mã trạng thái khi phản hồi không phải 2xx không?
Có thể truy xuất mã trạng thái cụ thể khi phản hồi 2xx không?
Có thể truy xuất phần thân HTTP khi phản hồi không phải 2xx không?

Cảm ơn!


1
Nếu bạn chưa được xác thực, bạn sẽ nhận được -999 theo thiết kế. Không chắc tại sao lại như vậy hoặc làm thế nào nó có thể được giải quyết ... Bạn đã giải quyết được vấn đề này chưa?
Guido Hendriks

Câu trả lời:


187

Đối với người dùng Swift 3.x / Swift 4.0 / Swift 5.0 với Alamofire> = 4.0 / Alamofire> = 5.0


response.response?.statusCode

Ví dụ chi tiết hơn:

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 chứa một hệ thống lỗi hoàn toàn mới, xem tại đây chi tiết )

Đối với người dùng Swift 2.x với 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 có thể cung cấp cho bạn lỗi Alamofire chẳng hạn. StatusCodeValidationFailed, FAILURE: Error Domain=com.alamofire.error Code=-6003. Đó là nếu bạn thực sự muốn get HTTP lỗi phản ứng nó tốt hơn để sử dụngresponse.response?.statusCode
Kostiantyn Koval

@KostiantynKoval Tôi đồng ý với bạn, bạn đã làm rõ đúng cách. Tôi đã cập nhật câu trả lời của mình cho rõ ràng
Alessandro Ornano

50

Trong trình xử lý hoàn thành với đối số responsebên dưới, tôi thấy mã trạng thái http là 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
                 }

Xin chào, statusCode 200 có bị lỗi không? yêu cầu của tôi đã được xử lý một cách chính xác ở phía máy chủ nhưng phản ứng thuộc Failure
perwyl

1
@perwyl Tôi không nghĩ rằng 200 là một lỗi http: xem stackoverflow.com/questions/27921537/...
wcochran

2
@perwyl tình trạng mã 200 được chỉ ra thành công, nếu máy chủ của bạn quay trở lại 200 và lỗi phản ứng chỉ ra (ví dụ một số tài sản được gọi là issuccess = false), sau đó bạn phải xử lý đó trong mã frontend của bạn
Parama Dharmika

16
    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):
    }

Điều này kích thích các phương pháp hay nhất của api
CESCO

URW :) Cố gắng triển khai Bộ định tuyến cho các yêu cầu của bạn. ;)
Abo3atef

11

Cách tốt nhất để lấy mã trạng thái bằng alamofire.

 Alamofire.request (URL) .responseJSON {
  phản hồi trong

  let status = response.response? .statusCode
  print ("STATUS \ (status)")

}

5

Sau responseJSONkhi hoàn thành, bạn có thể lấy mã trạng thái từ đối tượng phản hồi, có loại NSHTTPURLResponse?:

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

Điều này sẽ hoạt động bất kể mã trạng thái có nằm trong phạm vi lỗi hay không. Để biết thêm thông tin, hãy xem tài liệu NSHTTPURLResponse .

Đối với câu hỏi khác của bạn, bạn có thể sử dụng responseStringhàm để lấy phần nội dung trả lời thô. Bạn có thể thêm cái này ngoàiresponseJSON và cả hai sẽ được gọi.

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

3

Lỗi của bạn cho thấy rằng hoạt động đang bị hủy bỏ vì một số lý do. Tôi cần thêm chi tiết để hiểu tại sao. Nhưng tôi nghĩ rằng vấn đề lớn hơn có thể là vì điểm cuối của bạn https://host.com/a/pathkhông có thật, không có phản hồi máy chủ thực sự để báo cáo và do đó bạn đang thấynil .

Nếu bạn đạt được một điểm cuối hợp lệ cung cấp phản hồi thích hợp, bạn sẽ thấy một giá trị khác không cho res(sử dụng các kỹ thuật mà Sam đề cập) ở dạng một NSURLHTTPResponseđối tượng có các thuộc tính nhưstatusCode , v.v.

Ngoài ra, chỉ để rõ ràng, errorlà loại NSError. Nó cho bạn biết tại sao yêu cầu mạng không thành công. Mã trạng thái của lỗi ở phía máy chủ thực sự là một phần của phản hồi.

Hy vọng rằng sẽ giúp trả lời câu hỏi chính của bạn.


Nắm bắt tốt, tôi đã quá tập trung vào danh sách các câu hỏi ở phía dưới.
Sam

1
Nó thực sự nhận được mã 401 Trái phép vì tôi đang cố tình gửi sai mật khẩu để mô phỏng người dùng nhập sai mật khẩu của họ để tôi có thể bắt được trường hợp đó và đưa ra phản hồi cho người dùng. Đó không phải là URL thực mà tôi đang sử dụng, nhưng tôi đang sử dụng một URL hợp pháp dẫn đến thành công khi tôi gửi đúng mật khẩu. Đầu ra bảng điều khiển trong bài đăng ban đầu của tôi là đầu ra thực tế từ việc truy cập vào một URL thực (ngoại trừ URL là giả mạo) và bạn có thể thấy rằng resđối tượng là nilvậy, vì vậy câu trả lời này không hữu ích, xin lỗi.
GregT

Cảm ơn đã làm rõ. Chà, điều duy nhất nghi ngờ ở đây là lỗi -999 mà tôi chưa gặp phải, nhưng tài liệu cho thấy rằng yêu cầu đang bị hủy (vì vậy câu hỏi thậm chí nhận được phản hồi nên được tranh luận). Bạn đã thử in đối tượng phản hồi cho một loại lỗi khác không liên quan đến xác thực chưa? Chỉ tò mò.
rainpixels

ahhhh tôi nghĩ errorđang đề cập đến các phản hồi có mã trạng thái nằm ngoài phạm vi mà chúng tôi cung cấp validate(). Cảm ơn!!!
Gerald

3

Hoặc sử dụng kết hợp mẫu

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

Làm việc như người ở.
alasker

3

bạn có thể kiểm tra mã sau để biết trình xử lý mã trạng thái bằng 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)
        }
    }

nếu mã trạng thái không được xác thực, nó sẽ nhập lỗi trong trường hợp chuyển đổi


1

Dành cho người dùng Swift 2.0 với Alamofire> 2.0

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

1

Tôi cần biết cách lấy số mã lỗi thực tế.

Tôi kế thừa một dự án từ người khác và tôi phải lấy mã lỗi từ một .catchđiều khoản mà họ đã thiết lập trước đó cho 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)
}

Hoặc nếu bạn cần lấy nó từ responsegiá trị, hãy làm theo câu trả lời của @ 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)
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.