web-dev-qa-db-ja.com

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

残念ながら、生成されたエラーは、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ボディを取得すると、サーバー側でエラーの説明がそこに表示されるので便利です。

質問
2xx以外の応答でステータスコードを取得することは可能ですか?
2xx応答時に特定のステータスコードを取得することは可能ですか?
2xx以外の応答でHTTPボディを取得することは可能ですか?

ありがとう!

95
GregT

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

以下の引数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
                 }
45
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

Alamofireを使用してステータスコードを取得する最良の方法。

 Alamofire.request(URL).responseJSON {
 response in 
 
 let status = response.response?.statusCode 
 print( "STATUS\(状態)")

}
7
jamesdelacruz

responseJSON補完では、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
}
5
Sam

エラーは、何らかの理由で操作がキャンセルされていることを示しています。理由を理解するには、さらに詳細が必要です。しかし、より大きな問題は、エンドポイントhttps://Host.com/a/pathが偽物であるため、報告する実際のサーバー応答がないため、nilが表示される可能性があると思います。

適切な応答を提供する有効なエンドポイントに到達すると、resなどのプロパティを持つNSURLHTTPResponseオブジェクトの形式で、statusCodeの非nil値が表示されます(サムが言及した手法を使用)。

また、明確にするために、errorNSError型です。ネットワーク要求が失敗した理由がわかります。サーバー側の障害のステータスコードは、実際には応答の一部です。

あなたの主な質問に答えるのに役立つことを願っています。

3
rainypixels

またはパターンマッチングを使用する

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

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

ステータスコードが検証されない場合、スイッチケースでエラーが入力されます

2
Amr Angry

Alamofire> 2.0のSwift 2.0ユーザーの場合

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