web-dev-qa-db-fra.com

Swift Alamofire: Comment obtenir le code d'état de la réponse HTTP

J'aimerais récupérer le code d'état de la réponse HTTP (par exemple 400, 401, 403, 503, etc.) pour les demandes non satisfaites (et idéalement pour les succès également). Dans ce code, j'effectue une authentification d'utilisateur avec HTTP Basic et souhaite pouvoir informer l'utilisateur que l'authentification a échoué lorsque l'utilisateur a mal entré son mot de passe.

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

Malheureusement, l'erreur générée ne semble pas indiquer qu'un code d'état HTTP 409 a effectivement été reçu:

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

De plus, il serait bien de récupérer le corps HTTP lorsqu'une erreur se produit car mon côté serveur y mettra une description textuelle de l'erreur.

Questions
Est-il possible de récupérer le code de statut sur une réponse non 2xx?
Est-il possible de récupérer le code de statut spécifique après une réponse 2xx?
Est-il possible de récupérer le corps HTTP sur une réponse non 2xx?

Merci!

95
GregT

Pour Swift 3.x / Swift 4.0 / Swift 5.0 utilisateurs avec Alamofire> = 4.0 / Alamofire > = 5.0


response.response?.statusCode

Exemple plus détaillé:

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 contient un tout nouveau système d'erreur, regardez ici pour plus de détails)

Pour Swift 2.x utilisateurs avec 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
             }
}
165
Alessandro Ornano

Dans le gestionnaire d'achèvement avec l'argument response ci-dessous, le code de statut http se trouve dans 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
                 }
46
wcochran
    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):
    }
15
Abo3atef

Le meilleur moyen d’obtenir le code d’état en utilisant alamofire.

 Alamofire.request (URL) .responseJSON {
 Réponse in 
 
 Let status = response.response? .StatusCode 
 Print ("STATUS\(statut)")

}
7
jamesdelacruz

Dans votre complétion responseJSON, vous pouvez obtenir le code de statut de l'objet de réponse, qui a le type NSHTTPURLResponse?:

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

Cela fonctionnera que le code d'état soit dans la plage d'erreur ou non. Pour plus d'informations, consultez le documentation NSHTTPURLResponse .

Pour votre autre question, vous pouvez utiliser la fonction responseString pour obtenir le corps de réponse brut. Vous pouvez ajouter ceci en plus de responseJSON et les deux seront appelés.

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

Votre erreur indique que l'opération est annulée pour une raison quelconque. J'aurais besoin de plus de détails pour comprendre pourquoi. Mais je pense que le plus gros problème est peut-être que, puisque votre terminal https://Host.com/a/path est faux, il n’ya pas de réponse réelle du serveur à signaler, et vous voyez donc nil.

Si vous trouvez un noeud final valide qui fournit une réponse correcte, vous devriez voir une valeur non nulle pour res (à l'aide des techniques décrites par Sam) sous la forme d'un objet NSURLHTTPResponse avec des propriétés telles que statusCode, etc.

De plus, juste pour être clair, error est de type NSError. Il vous explique pourquoi la requête réseau a échoué. Le code d'état de la panne côté serveur fait en réalité partie de la réponse.

J'espère que cela aide à répondre à votre question principale.

3
rainypixels

Ou utilisez la correspondance de modèle

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

vous pouvez vérifier le code suivant pour le gestionnaire de code d'état par 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)
        }
    }

si le code d’état n’est pas valide, il sera saisi de l’échec en cas de commutation

2
Amr Angry

Pour Swift 2.0 utilisateurs d'Alamofire> 2.0

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