Swift Alamofire: Cara mendapatkan kode status respons HTTP

106

Saya ingin mendapatkan kembali kode status tanggapan HTTP (misalnya 400, 401, 403, 503, dll) untuk kegagalan permintaan (dan idealnya juga untuk keberhasilan). Dalam kode ini, saya melakukan otentikasi pengguna dengan HTTP Basic dan ingin dapat mengirim pesan kepada pengguna bahwa otentikasi gagal ketika pengguna salah mengetikkan sandi mereka.

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

Sayangnya, kesalahan yang dihasilkan tampaknya tidak menunjukkan bahwa kode status HTTP 409 benar-benar diterima:

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

Selain itu, alangkah baiknya untuk mengambil badan HTTP ketika terjadi kesalahan karena sisi server saya akan meletakkan deskripsi tekstual tentang kesalahan di sana.

Pertanyaan
Apakah mungkin untuk mengambil kode status setelah respon non-2xx?
Apakah mungkin untuk mengambil kode status tertentu setelah respons 2xx?
Apakah mungkin untuk mengambil isi HTTP setelah respons non-2xx?

Terima kasih!

GregT
sumber
1
Jika Anda tidak diautentikasi, Anda menerima -999 dengan desain. Tidak yakin mengapa ini atau bagaimana ini bisa diselesaikan ... Apakah Anda menyelesaikan ini?
Guido Hendriks

Jawaban:

187

Untuk pengguna Swift 3.x / Swift 4.0 / Swift 5.0 dengan Alamofire> = 4.0 / Alamofire> = 5.0


response.response?.statusCode

Lebih banyak contoh verbose:

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 berisi sistem kesalahan yang sama sekali baru, lihat di sini untuk detailnya)

Untuk pengguna Swift 2.x dengan 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
             }
}
Alessandro Ornano
sumber
response.result.error dapat memberikan Anda kesalahan Alamofire, misalnya. StatusCodeValidationFailed, FAILURE: Error Domain=com.alamofire.error Code=-6003. Jika Anda benar-benar ingin mendapatkan kesalahan respons HTTP, lebih baik bagi penggunaresponse.response?.statusCode
Kostiantyn Koval
@KostiantynKoval Saya setuju dengan Anda, Anda telah melakukan klarifikasi yang tepat. Saya memperbarui jawaban saya untuk kejelasan
Alessandro Ornano
50

Dalam penangan penyelesaian dengan argumen di responsebawah ini saya menemukan kode status http ada di 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
                 }
wcochran.dll
sumber
Hai, apakah statusCode 200 akan gagal? permintaan saya ditangani dengan benar di sisi server tetapi tanggapannya berada di bawah Kegagalan
perwyl
1
@perwyl Saya tidak berpikir 200 adalah kesalahan http: lihat stackoverflow.com/questions/27921537/…
wcochran
2
Kode status @perwyl 200 menunjukkan keberhasilan, jika server Anda mengembalikan 200 dan respons menunjukkan kesalahan (yaitu beberapa properti bernama issuccess = false), maka Anda harus menanganinya di kode frontend Anda
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):
    }
Abo3atef
sumber
Ini merangsang praktik terbaik api
CESCO
URW :) Coba terapkan Router untuk permintaan Anda. ;)
Abo3atef
11

Cara terbaik untuk mendapatkan kode status menggunakan alamofire.

 Alamofire.request (URL) .responseJSON {
  respon dalam

  biarkan status = response.response? .statusCode
  cetak ("STATUS \ (status)")

}
jamesdelacruz
sumber
5

Setelah responseJSONmenyelesaikannya, Anda bisa mendapatkan kode status dari objek respons, yang memiliki tipe NSHTTPURLResponse?:

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

Ini akan berfungsi terlepas dari apakah kode status berada dalam kisaran kesalahan. Untuk informasi lebih lanjut, lihat dokumentasi NSHTTPURLResponse .

Untuk pertanyaan Anda yang lain, Anda bisa menggunakan responseStringfungsi tersebut untuk mendapatkan isi respons mentah. Anda dapat menambahkan ini sebagai tambahan responseJSONdan keduanya akan dipanggil.

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

Kesalahan Anda menunjukkan bahwa operasi dibatalkan karena alasan tertentu. Saya membutuhkan lebih banyak detail untuk memahami alasannya. Tapi saya pikir masalah yang lebih besar mungkin karena titik akhir Anda https://host.com/a/pathpalsu, tidak ada respons server nyata untuk dilaporkan, dan karenanya Anda melihatnya nil.

Jika Anda mencapai titik akhir valid yang memberikan respons yang tepat, Anda akan melihat nilai bukan-nil untuk res(menggunakan teknik yang disebutkan Sam) dalam bentuk NSURLHTTPResponseobjek dengan properti seperti statusCode, dll.

Juga, hanya untuk memperjelas, erroradalah tipe NSError. Ini memberi tahu Anda mengapa permintaan jaringan gagal. Kode status kegagalan di sisi server sebenarnya adalah bagian dari respons.

Semoga itu bisa membantu menjawab pertanyaan utama Anda.

rainypixels
sumber
Tangkapan bagus, saya terlalu fokus pada daftar pertanyaan di bawah.
Sam
1
Sebenarnya menerima kode 401 Tidak Sah karena saya sengaja mengirimkan kata sandi yang salah untuk mensimulasikan pengguna salah mengetik kata sandi mereka sehingga saya dapat menangkap kasus itu dan memberikan umpan balik kepada pengguna. Itu bukan URL sebenarnya yang saya gunakan, tetapi saya menggunakan URL yang sah yang berhasil ketika saya mengirim kata sandi yang benar. Output konsol di posting asli saya adalah output aktual dari mengenai URL asli (kecuali bahwa URL itu palsu) dan Anda dapat melihat bahwa resobjeknya adalah nil, jadi jawaban ini tidak membantu, maaf.
GregT
Terima kasih telah menjelaskan. Nah, satu-satunya hal yang dicurigai di sini adalah kesalahan -999 yang belum saya temui, tetapi dokumentasi menyarankan bahwa permintaan dibatalkan (jadi pertanyaan tentang menerima tanggapan harus diperdebatkan). Sudahkah Anda mencoba mencetak objek respons untuk jenis kesalahan lain yang tidak terkait dengan autentikasi? Hanya penasaran.
rainypixels
ahhhh saya pikir errormengacu pada tanggapan dengan kode status yang berada di luar kisaran yang kami sediakan validate(). Terima kasih!!!
Gerald
3

Atau gunakan pencocokan pola

if let error = response.result.error as? AFError {
   if case .responseValidationFailed(.unacceptableStatusCode(let code)) = error {
       print(code)
   }
}
mbryzinski
sumber
Bekerja seperti pesona.
alasker
3

Anda dapat memeriksa kode berikut untuk penangan kode status oleh 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)
        }
    }

jika kode status tidak divalidasi itu akan memasukkan kegagalan dalam kasus sakelar

Amr Marah
sumber
1

Untuk pengguna Swift 2.0 dengan Alamofire> 2.0

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

Saya perlu tahu cara mendapatkan nomor kode kesalahan yang sebenarnya.

Saya mewarisi proyek dari orang lain dan saya harus mendapatkan kode kesalahan dari .catchklausa yang sebelumnya mereka siapkan untuk Alamofire:

} .catch { (error) in

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

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

Atau jika Anda perlu mendapatkannya dari responsenilai ikuti jawaban @ mbryzinski

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)
})
Lance Samaria
sumber