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