Swift Alamofire: как получить код статуса ответа HTTP
Я хотел бы получить код статуса ответа 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")
}
К сожалению, полученная ошибка не указывает на то, что фактически был получен код состояния 409 HTTP:
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
Для пользователей 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
}
}
Ответ 2
В обработчике завершения с аргументом 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
}
Ответ 3
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):
}
Ответ 4
Лучший способ получить код состояния с помощью alamofire.
Alamofire.request(URL).responseJSON {
response in
let status = response.response?.statusCode
print("STATUS \(status)")
}
Ответ 5
В завершении 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
}
Ответ 6
Ваша ошибка указывает на то, что операция по какой-либо причине отменяется. Мне нужно больше деталей, чтобы понять, почему. Но я думаю, что большая проблема может заключаться в том, что, поскольку ваша конечная точка https://host.com/a/path
является фиктивной, нет реального ответа сервера на отчет, и, следовательно, вы видите nil
.
Если вы набрали действительную конечную точку, которая отвечает правильному ответу, вы должны увидеть значение non-nil для res
(используя методы Сэма) в форме объекта NSURLHTTPResponse
со свойствами, такими как statusCode
и т.д.
Также, чтобы быть ясным, error
имеет тип NSError
. Он сообщает вам, почему сетевой запрос не удался. Код состояния сбоя на стороне сервера фактически является частью ответа.
Надеюсь, что поможет ответить на ваш главный вопрос.
Ответ 7
Или используйте сопоставление с образцом
if let error = response.result.error as? AFError {
if case .responseValidationFailed(.unacceptableStatusCode(let code)) = error {
print(code)
}
}
Ответ 8
вы можете проверить следующий код для обработчика кода состояния с помощью 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)
}
}
если код состояния не проверяется, он будет вводить сбой в случае коммутатора
Ответ 9
Для пользователей Swift 2.0 с Alamofire > 2.0
Alamofire.request(.GET, url)
.responseString { _, response, result in
if response?.statusCode == 200{
//Do something with result
}
}