Alamofire在遇到错误的HTTP状态码时返回".Success"

34

我有一个非常简单的情况,但我遇到了困难。我正在使用Alamofire在rest API上注册用户。第一次调用注册成功,用户可以登录。第二次调用,当尝试使用相同的电子邮件地址注册时,服务器应该返回HTTP状态码409。然而,Alamofire返回一个空的请求和响应的.Success。我已经使用Postman测试了这个API,它正确地返回了409。

为什么Alamofire没有返回.Failure(error),其中错误具有状态代码信息等?

这是我每次运行相同输入的调用。

Alamofire.request(.POST, "http://localhost:8883/api/0.1/parent", parameters: registrationModel.getParentCandidateDictionary(), encoding: .JSON).response(completionHandler: { (req, res, d, e) -> Void in
        print(req, res, d, e)
    })
4个回答

85

来自Alamofire的手册

验证

默认情况下,无论响应内容如何,Alamofire都会将任何完成的请求视为成功。在响应处理程序之前调用 validate 可以在响应具有不可接受的状态代码或 MIME 类型时生成错误。

您可以使用 validate 方法手动验证状态码,同样也是从手册中获取:

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
     .validate(statusCode: 200..<300)
     .validate(contentType: ["application/json"])
     .response { response in
         print(response)
     }

或者您可以使用没有参数的validate进行半自动验证状态码和内容类型:

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
     .validate()
     .responseJSON { response in
         switch response.result {
         case .success:
             print("Validation Successful")
         case .failure(let error):
             print(error)
         }
     }

2
手册页面的链接指向Alamofire主页。 正确的链接:验证 - andriy_fedin
更新了链接。谢谢@andriy_fedin - David Berry

17

如果使用 response,您可以检查 NSHTTPURLResponse 参数:

Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
    .response { response in
        if response.response?.statusCode == 409 {
            // handle as appropriate
        }
}

默认情况下,4xx状态码不被视为错误,但您可以使用validate将其视为错误,然后将其纳入到更广泛的错误处理中:

Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
    .validate()
    .response() { response in
        guard response.error == nil else {
            // handle error (including validate error) here, e.g.

            if response.response?.statusCode == 409 {
                // handle 409 here
            }
            return
        }
        // handle success here
}

或者,如果使用 responseJSON

Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
.validate()
.responseJSON() { response in
    switch response.result {
    case .failure:
        // handle errors (including `validate` errors) here

        if let statusCode = response.response?.statusCode {
            if statusCode == 409 {
                // handle 409 specific error here, if you want
            }
        }
    case .success(let value):
        // handle success here
        print(value)
    }
}

上面是 Alamofire 4.x。查看此答案的以前版本,请参见 Alamofire 的早期版本


2
这行代码 if statusCode == 409 { //在这里处理特定的409错误,如果您想要} - 从服务器端检索错误消息的最佳方法是什么?例如返回错误401并让服务器通知用户登录凭据不正确。最佳实践是什么? - luke
1
@luke - 通常你只需要使用状态码。Web服务通常在响应体中包含一些文本(例如,在Alamofire 4.x中,使用response.data),但据我所知,其格式并未标准化,因此您需要检查来自特定服务器的响应并查看您可以解析出什么。如果您不想经历所有这些,您可以只查看statusCode。顺便说一句,注意并非所有身份验证错误都会导致401状态码,而是会导致错误并且您必须查看Error对象的code - Rob

5

0

这是我用于AlamoFire错误捕获的代码:

switch response.result {
                case .success(let value):
                    completion(.success(value))
                case .failure(var error):

                    var errorString: String?

                    if let data = response.data {
                        if let json = try? (JSONSerialization.jsonObject(with: data, options: []) as! [String: String]) {
                            errorString = json["error"]

                        }
                    }
                    let error = MyError(str: errorString!)
                    let x = error as Error
                    print(x.localizedDescription)
                    completion(.failure(x))

                }

以及MyError类的定义:

class MyError: NSObject, LocalizedError {
        var desc = ""
        init(str: String) {
            desc = str
        }
        override var description: String {
            get {
                return "MyError: \(desc)"
            }
        }
        //You need to implement `errorDescription`, not `localizedDescription`.
        var errorDescription: String? {
            get {
                return self.description
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接