6

Using Alamofire, is it possible to have a function to handle the header response before downloading the complete file?

For example:

Our app uses the same elements on multiple pages. These elements are collected using request. Each request has his own hash (md5 checksum). We are sending this hash in the headers & i want to abort the request if the hash is recognised in the cache system.

Example implementation

APIManager.sharedManager.request(url, method: method, parameters: parameters)

            .doSomethingHere {
             //I want to read the headers here, before the data is fetched from the server.
             //There needs to be an option here to cancel the request.
            }

            .responseJSON { response in
             //If the request isn't cancel in the function above. The data should be here.
            }
}

Edit: Solution (Alamofire implementation SWIFT 3)

APIManager.sharedManager.delegate.dataTaskDidReceiveResponse =
        {(session:URLSession, dataTask:URLSessionDataTask, response:URLResponse) -> URLSession.ResponseDisposition in

            if let httpResponse = response as? HTTPURLResponse {
                //Do something with headers here. If you don't want to continue the request:
                return URLSession.ResponseDisposition.cancel

            }       

            return URLSession.ResponseDisposition.allow
    }

APIManager.sharedManager.request(url, method: method, parameters: parameters)
                .responseJSON { response in
                 //Response contains no data if it was canceled. 
                }
    }
Bas
  • 780
  • 5
  • 17
  • You can only achieve what you want using two requests. The response headers are part of the response itself, so how could you check the headers before getting the response? – Dávid Pásztor Oct 04 '17 at 14:32
  • Hi David. I saw that my title was incorrect. I want to validate the response headers and then decide if i want to download the full response body. – Bas Oct 04 '17 at 14:53
  • As @DávidPásztor mentioned you can not get the headers before the response. Headers are part of the response. Either you have to use two requests or you need to handle it in the server side. If the headers are not validated , it can send whatever you want ( error messages or status code etc ) If you want to you can see all the header using this print(response.response?.allHeaderFields) – Udaya Sri Oct 04 '17 at 15:05
  • 1
    Is should be possible to abort the request when the headers are received? Like https://stackoverflow.com/questions/17390319/php-curl-inspecting-response-headers-before-downloading-body – Bas Oct 04 '17 at 15:19
  • @Bas your question is about iOS using Swift, not PHP, so that question has no relevance to yours – Dávid Pásztor Oct 04 '17 at 17:33
  • 1
    It is relevant, because it is using the same technique. iOS is performing an HTTP request (like PHP CURL does), and i want alamofire to stop fetching data based on the data in the header. – Bas Oct 04 '17 at 21:34
  • @Bas Lets try HEAD request in Alamofire, it may works! http://www.tutorialspoint.com/http/http_methods.htm – arunjos007 Oct 11 '17 at 09:30
  • 1
    That's exactly what i want, but when the header contains some information i want to "continue" the stream with the full body without loosing the connection / let the server calculate the body again. – Bas Oct 11 '17 at 10:23

1 Answers1

3

The header is in-fact a part of the response so you may have to make two requests in order to do this.

I gather from the comments that this is something you like to avoid. In this case what you could do is send the hash in the request itself. The server then decides whether or not to return the data.

To simplify :

  1. Send the hash in the request.
  2. The server checks if the hash exists
  3. Empty response (or some status code) if it does, response with data if it doesn't.

EDIT :

There's a better solution though... You can use the urlSession(_:dataTask:didReceive:completionHandler:) method of the URLSessionDataDelegate.

You can check the hash returned in the header. Then just pass a constant in the completion handler of this method indicating whether to continue with the task or cancel it. More on that here.

EDIT 2:

There is yet another solution using HTTP/2 Server Push protocol, although it's pretty much unchartered territory for now since it hasn't been applied in this way yet.

With server push the server sends "push promises" along with the first response. These promises are small frames that inform the client about subsequent responses that the server will send. So, in this case, you could return the hash as the first response and a push promise for the actual data.

Further reading :

NSAdi
  • 1,243
  • 9
  • 19
  • This is our backup plan, but i don't prefer this way because there can be multiple response cached. For example the request http://server-url.com/request/example/request/ can have 100 difference responses. With your solution I would need to send 100 hashes with the request. – Bas Oct 17 '17 at 11:30
  • Yeah, doesn't seem right. I've edited the answer with an alternate solution. Think it should be a good fit for your requirements. – NSAdi Oct 18 '17 at 02:09
  • Your edit is totally what I was looking for. I've updated my initial post. – Bas Oct 18 '17 at 14:44