What Is the Use of the Validate() Method in Alamofire.Request

How to handle error when using validate() in Alamofire request?

In order to retry your requests, you must produce an error at some point in Alamofire's request pipeline. validate() does this for you automatically, letting the request be retried before your response serializer(s) are called. You can either customize validate() to only care about the status codes you want, or you can create a custom response serializer and throw the error there. You could customize your validation with your own set of status codes:

var allowedStatusCodes = Set(200..<500)
allowedStatusCodes.remove(403)

AF.request(...).validate(statusCode: allowedStatusCodes).response { ... }

Validate Alamofire Response for both HTTP 200 and 500 status codes

I can make Alamofire validate only HTTP 200 and HTTP 500 status codes by putting status codes inside an array and give as an input. Hope It helps:

Alamofire.request(route).validate(statusCode: [200,500]).responseJSON

How could I check in Alamofire my request is sent?

Response Validation

By default, Alamofire treats any completed request to be successful, regardless of the content of the response. Calling validate before a response handler causes an error to be generated if the response had an unacceptable status code or MIME type.

Manual Validation

Alamofire.request("https://httpbin.org/get")
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.responseData { response in
switch response.result {
case .success:
print("Validation Successful")
case .failure(let error):
print(error)
}
}

Automatic Validation

Automatically validates status code within 200..<300 range, and that the Content-Type header of the response matches the Accept header of the request, if one is provided.

Alamofire.request("https://httpbin.org/get").validate().responseJSON { response in
switch response.result {
case .success:
print("Validation Successful")
case .failure(let error):
print(error)
}
}

Statistical Metrics

Timeline
Alamofire collects timings throughout the lifecycle of a Request and creates a Timeline object exposed as a property on all response types.

Alamofire.request("https://httpbin.org/get").responseJSON { response in
print(response.timeline)
}

The above reports the following Timeline info:

  • Latency: 0.428 seconds
  • Request Duration: 0.428 seconds
  • Serialization Duration: 0.001 seconds
  • Total Duration: 0.429 seconds

Taken from Alamofire Usage. U can have e deeper look.

Alamofire Enhancement of validate()

First of all, you should specify the expected status codes in the call to validate. Let's assume your valid expected codes are 200, 400,500, 404. Then you don't even have to check the response result, just verify that the response carries no error, according to the documentation of the validate method:

If validation fails, subsequent calls to response handlers will have an associated error.

So in your case, I think your code could be simplified as following (I'm assuming that the JSON class that appears in your code is SwiftyJSON):

Alamofire.request(route)
.validate(statusCode: [200, 400,500, 404])
.responseJSON(completionHandler: { (response: Response<AnyObject, NSError>) -> Void in
if let error = response.result.error {
self.delegate.didFailCheckingHeader(error)
} else if let jsonObject: AnyObject = response.result.value {
let json = JSON(jsonObject)
self.delegate.didSuccessRequestToken(json)
}
})

It should work like that. Otherwise, you might want to check if the server is actually returning the expected status codes

Alamofire retry doesn't work with validate()

You used ApiError in the retry method signature, which breaks the conformance. It works with RequestInterceptor because that type provides a default implementation. Match the proper signature, ensure you have no local types shadowing the types in the signature, and it should work correctly.

Swift Alamofire: How to validate both a valid request and a valid response code

It helps to read the docs..... I ended up using the Alamofire validate API method:

Alamofire.request(.GET, getUrl("mystuff")).validate().responseData { response in
guard response.result.error == nil else {
//Handle error
}
}

This handles the validation on the return code as well as general connection issues. Also handles validation on the content type (see the linked doc for more info...)

Alamofire DownloadRequest validate and get the response data from the server

Bottom line, if you want a Result type, you're going to have to use responseJSON. But you can't do that with a simple DownloadRequest. This presents a few possible options:

  1. If you really want to use a download request, you'll have specify the destination for the downloaded file when you create the DownloadRequest, using the to parameter, e.g.

    // you may have to create the directory if it hasn't been created yet

    try! FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

    // then you can use it:

    let destination = DownloadRequest.suggestedDownloadDestination(for: .downloadsDirectory)
    let req = Alamofire.download("http://httpbin.org/get", to: destination)
    perform(download: req)

    And then:

    func perform(download request: DownloadRequest) {
    request
    .validate()
    .downloadProgress { progress in
    print(progress)
    }
    .responseJSON { response in
    switch response.result {
    case .success(let value): print(value)
    case .failure(let error): print(error)
    }
    }
    }

    If you do this, you may want to remove that file at response.destinationURL when you're done with it.

  2. IMHO, the theoretical advantage of download tasks is that the peak memory usage is lower. But if you're just going to turn around and load the contents of that file into some JSON object, I think that diminishes any advantage yielded by download tasks. So, the question is why not use data task, instead? You can just do a DataRequest:

    let req = Alamofire.request("http://httpbin.org/get")
    perform(get: req)

    And then:

    func perform(get request: DataRequest) {
    request
    .validate()
    .downloadProgress { progress in
    print(progress)
    }
    .responseJSON { response in
    switch response.result {
    case .success(let value): print(value)
    case .failure(let error): print(error)
    }
    }
    }

Personally, I'd lean towards a data task rather than the download task for JSON unless there's some reason you need it (e.g. background sessions), but it's up to you.

How to best modify error messages from -validate method on Alamofire

The easiest way would be to act on the error once it reaches your app code. You probably don't want to create a custom validate method that overrides the default Alamofire behavior because your case is VERY specific.

In general, you would set your acceptable status codes and use the validate(statusCodes:) method. Then in your response logic in your app code, switch on the error and create custom app representations of each case. In this case, a 403 means that the incorrect credentials were used which only your application knows. Hence, it should live in your app code, not in an Alamofire validation extension. My two cents...



Related Topics



Leave a reply



Submit