Swift Alamofire: How to get the HTTP response status code

我希望检索请求失败的 HTTP 响应状态代码(例如400、401、403、503等)(对于成功的请求也是理想的)。在这段代码中,我使用 HTTPBasic 执行用户身份验证,并希望能够向用户发送消息,说明当用户输错密码时,身份验证失败。

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 主体是很好的,因为我的服务器端将在那里放置错误的文本描述。

Questions
是否可以在非2xx 响应上检索状态代码?
是否有可能在2xx 响应后检索特定的状态代码?
是否可以在非2xx 响应上检索 HTTP 主体?

谢谢!

130246 次浏览

In your responseJSON completion, you can get the status code from the response object, which has a type of NSHTTPURLResponse?:

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

无论状态代码是否在错误范围内,这都将起作用。有关更多信息,请参见 NSHTTPURLResponse documentation

对于您的其他问题,您可以使用 responseString函数来获得原始的响应主体。除了 responseJSON之外,还可以添加这个函数,这两个函数都将被调用。

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

您的错误指示由于某种原因正在取消操作。我需要更多细节来了解原因。但是我认为更大的问题可能是因为您的端点 https://host.com/a/path是假的,没有真正的服务器响应来报告,因此您看到的是 nil

如果遇到一个提供正确响应的有效端点,应该会看到 res的非零值(使用 Sam 提到的技术) ,其形式是具有 statusCode等属性的 NSURLHTTPResponse对象。

另外,需要说明的是,errorNSError类型。它告诉您网络请求失败的原因。服务器端故障的状态代码实际上是响应的一部分。

希望这有助于回答你的主要问题。

对于 Alamofire > 2.0的 Swift 2.0用户

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

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包含一个全新的错误系统,详情请查看 给你)

对于使用 Alamofire > = 3.0Swift 2. x用户

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

在下面参数为 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
}

或者用模式匹配

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

使用 alamofire 获取状态代码的最佳方法。

Alamofire.request(URL).responseJSON {
response in


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


}

您可以通过 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)
}
}

如果状态代码没有被验证,它将在开关情况下输入故障

I needed to know how to get the actual error code number.

我从别人那里继承了一个项目,我必须从他们之前为 Alamofire 设置的 .catch子句中获得错误代码:

} .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值中得到它,请按照 < a href = “ https://stackoverflow. com/a/42862157/4833705”>@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)
})

斯威夫特3. x/Swift 4.0/Swift 5.0用户使用 Alamofire > = 5.0

使用请求修饰符来增加和减少超时间隔。

Alamofire 的 请求创建方法为定制提供了最常见的参数,但有时这些参数还不够。通过传递的值创建的 URLRequest 可以在创建请求时通过使用 RequestModfier 闭包进行修改。例如,要将 请求网址 间隔时间设置为120秒,请修改闭包中的请求。

var manager = Session.default
manager.request(urlString, method: method, parameters: dict, headers: headers, requestModifier: { $0.timeoutInterval = 120 }).validate().responseJSON { response in

OR

RequestAmendment 还可以处理尾随闭包语法。

var manager = Session.default
manager.request("https://httpbin.org/get") { urlRequest in
urlRequest.timeoutInterval = 60
urlRequest.allowsConstrainedNetworkAccess = false
}
.response(...)