Swift Alamofire: HTTP yanıt durum kodu nasıl alınır


106

İstek hataları için (ve ideal olarak başarılar için de) HTTP yanıt durum kodunu (ör. 400, 401, 403, 503, vb.) Almak istiyorum. Bu kodda, HTTP Temel ile kullanıcı kimlik doğrulaması yapıyorum ve kullanıcı parolasını yanlış yazdığında kimlik doğrulamasının başarısız olduğu konusunda kullanıcıya mesaj gönderebilmek istiyorum.

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

Maalesef, üretilen hata 409 HTTP durum kodunun gerçekten alındığını göstermiyor:

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

Ek olarak, bir hata oluştuğunda HTTP gövdesini almak güzel olurdu çünkü sunucu tarafım oraya hatanın metinsel bir tanımını koyacak.

Sorular
2xx olmayan bir yanıtta durum kodunu almak mümkün müdür?
2xx yanıtı üzerine özel durum kodunu almak mümkün müdür?
2xx olmayan bir yanıt üzerine HTTP gövdesini almak mümkün müdür?

Teşekkürler!


1
Kimlik doğrulaması yapılmadıysa, tasarım gereği bir -999 alırsınız. Bunun neden olduğundan veya nasıl çözülebileceğinden emin değilim ... Bunu çözdün mü?
Guido Hendriks

Yanıtlar:


187

İçin Swift 3.x / Swift 4.0 / Swift 5.0 ile kullanıcılar Alamofire> = 4.0 / Alamofire> = 5.0


response.response?.statusCode

Daha ayrıntılı örnek:

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 tamamen yeni bir hata sistemi içerir, ayrıntılar için buraya bakın)

İçin Swift 2.x kullanıcılara 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
             }
}

response.result.error örneğin size Alamofire hatası verebilir. StatusCodeValidationFailed, FAILURE: Error Domain=com.alamofire.error Code=-6003. Aslında HTTP yanıt hatası almak istiyorsanız, kullanıcı için daha iyidirresponse.response?.statusCode
Kostiantyn Koval

@KostiantynKoval Size katılıyorum, uygun bir açıklama yaptınız. Cevabımı netlik için güncelledim
Alessandro Ornano

50

responseAşağıdaki bağımsız değişkenli tamamlama işleyicisinde http durum kodunun içinde olduğunu görüyorum 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
                 }

Merhaba, statusCode 200 başarısız olur mu? isteğim sunucu tarafında doğru bir şekilde ele alındı, ancak yanıt Hata kategorisine düşüyor
perwyl

1
@perwyl 200'ün bir http hatası olduğunu düşünmüyorum: bkz. stackoverflow.com/questions/27921537/…
wcochran

2
@perwyl durum kodu 200, sunucunuz 200 döndürdüyse ve hata belirten yanıt (yani, issuccess = false olarak adlandırılan bir özellik), bunu ön uç kodunuzda işlemeniz gerekir
Parama Dharmika

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

Bu
API'nin

URW :) İstekleriniz için Yönlendirici uygulamaya çalışın. ;)
Abo3atef

11

Alamofire kullanarak durum kodunu almanın en iyi yolu.

 Alamofire.request (URL) .responseJSON {
  cevap

  let status = response.response? .statusCode
  baskı ("DURUM \ (durum)")

}

4

Senin içinde responseJSONtamamlanması, sen bir türü olan tepki nesne, durum kodunu alabilirsiniz NSHTTPURLResponse?:

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

Bu, durum kodunun hata aralığında olup olmadığına bakılmaksızın çalışacaktır. Daha fazla bilgi için NSHTTPURLResponse belgelerine göz atın .

Diğer sorunuz responseStringiçin, ham yanıt gövdesini elde etmek için işlevi kullanabilirsiniz . Buna ek olarak ekleyebilirsiniz responseJSONve her ikisi de çağrılacaktır.

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

3

Hatanız, işlemin herhangi bir nedenle iptal edildiğini gösterir. Nedenini anlamak için daha fazla detaya ihtiyacım var. Ancak bence daha büyük sorun, uç noktanız https://host.com/a/pathsahte olduğu için, rapor edilecek gerçek bir sunucu yanıtı olmaması ve dolayısıyla görüyorsunuz nil.

Uygun bir yanıt veren geçerli bir uç noktaya ulaşırsanız , vb. Özelliklere sahip resbir NSURLHTTPResponsenesne biçiminde (Sam'in bahsettiği teknikleri kullanarak) için sıfır olmayan bir değer görmelisiniz statusCode.

Ayrıca, açık olmak gerekirse, errortipte NSError. Ağ isteğinin neden başarısız olduğunu size söyler. Sunucu tarafındaki arızanın durum kodu aslında yanıtın bir parçasıdır.

Umarım bu, ana sorunuzu yanıtlamanıza yardımcı olur.


İyi yakaladım, en alttaki soru listesine çok odaklandım.
Sam

1
Aslında bir 401 Yetkisiz kodu alıyor çünkü bir kullanıcının şifresini yanlış yazmasını simüle etmek için kasıtlı olarak yanlış şifre gönderiyorum, böylece bu durumu yakalayabilir ve kullanıcıya geri bildirimde bulunabilirim. Bu, kullandığım gerçek URL değil, ancak doğru şifreyi gönderdiğimde başarılı olan yasal bir URL kullanıyorum. Orijinal gönderimdeki konsol çıktısı, gerçek bir URL'ye (URL'nin sahte olması dışında) ulaşmanın gerçek çıktısıdır ve resnesnenin olduğunu görebilirsiniz nil, bu nedenle bu yanıt yardımcı olmuyor, üzgünüm.
GregT

Açıkladığınız için teşekkürler. Öyleyse, burada şüpheli olan tek şey, bununla karşılaşmadığım -999 hatasıdır, ancak belgeler, isteğin iptal edildiğini gösteriyor (bu nedenle, bir yanıt alma sorusu bile tartışmalı olmalıdır). Kimlik doğrulamasıyla ilgili olmayan farklı bir hata türü için yanıt nesnesini yazdırmayı denediniz mi? Sadece merak.
rainypixels

ahhhh error, sağladığımız aralığın dışında olan durum kodlu yanıtlara atıfta bulunduğunu düşündüm validate(). Teşekkürler!!!
Gerald

3

Veya desen eşleştirmeyi kullanın

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

Bir cazibe gibi çalıştı.
alasker

3

alamofire'ın durum kodu işleyicisi için aşağıdaki kodu kontrol edebilirsiniz

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

durum kodu doğrulanmazsa, anahtar durumunda arızaya girilecektir


1

Alamofire> 2.0 olan Swift 2.0 kullanıcıları için

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

1

Gerçek hata kodu numarasını nasıl alacağımı bilmem gerekiyordu.

Başka birinden bir proje miras aldım ve hata kodlarını .catchdaha önce Alamofire için ayarladıkları bir cümleden almak zorunda kaldım:

} .catch { (error) in

    guard let error = error as? AFError else { return }
    guard let statusCode = error.responseCode else { return }

    print("Alamofire statusCode num is: ", statusCode)
}

Ya da responsedeğerinden almanız gerekiyorsa @ mbryzinski'nin cevabını takip edin

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)
})
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.