ios Alamofire 返回 .Success 错误 HTTP 状态代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34737574/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:33:56  来源:igfitidea点击:

Alamofire returns .Success on error HTTP status codes

iosswiftalamofire

提问by Craigt

I have a pretty simple scenario that I'm struggling with. I'm using Alamofire to register a user on a rest API. The first call to register is successful and the user can log in. The second call, when trying to register with the same email address should result in a HTTP status code 409 from the server. Alamofire, however, returns a .Success with an empty request and response. I have tested this this API with postman and it correctly returns a 409.

我有一个非常简单的场景,我正在努力解决。我正在使用 Alamofire 在 rest API 上注册用户。第一次注册调用成功,用户可以登录。第二次调用,当尝试使用相同的电子邮件地址注册时,应该会导致来自服务器的 HTTP 状态代码 409。但是,Alamofire 会返回一个 .Success 并带有一个空的请求和响应。我已经用邮递员测试了这个 API,它正确地返回了 409。

Why is Alamofire not returning .Failure(error), where the error has status code info etc?

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

Here is the call I run with the same input each time.

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

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

回答by David Berry

From the Alamofire manual:

从 Alamofire手册

Validation

By default, Alamofire treats any completed request to be successful, regardless of the content of the response. Calling validate before a response handler causes an error to be generated if the response had an unacceptable status code or MIME type.

验证

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

You can manually validate the status code using the validatemethod, again, from the manual:

您可以validate再次使用手册中的方法手动验证状态代码:

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

Or you can semi-automatically validate the status code and content-type using the validatewith no arguments:

或者,您可以使用不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)
         }
     }

回答by Rob

If using response, you can check the NSHTTPURLResponseparameter:

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

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

By default, 4xx status codes aren't treated as errors, but you can use validateto treat it as an such and then fold it into your broader error handling:

默认情况下,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
}

Or, if using responseJSON:

或者,如果使用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)
    }
}

The above is Alamofire 4.x. See previous rendition of this answer for earlier versions of Alamofire.

以上是Alamofire 4.x。有关Alamofire 的早期版本,请参阅此答案的先前版本

回答by Lilo

if you use validate() you'll loose the error message from server, if you want to keep it, see this answer https://stackoverflow.com/a/36333378/1261547

如果您使用validate(),您将从服务器丢失错误消息,如果您想保留它,请参阅此答案https://stackoverflow.com/a/36333378/1261547

回答by Payam Khaninejad

Here is my code for AlamoFire error catching:

这是我的 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))

                }

and the MyError class difinition:

和 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
            }
        }
    }