Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercepting EVERY response with Alamofire

I'm just exploring using Alamofire and it is excellent but I'd like to do something that I feel is possible just not sure how.

Our authentication with the server uses one-time-use bearer tokens. So for every request made I have to store the new token sent down with that request.

What I'd like to do is intercept every response that comes back and check the Authorisation header. Save it to disk and then forward to the place waiting for the actual data.

Is this possible with Alamofire?

If so, please could you point me in the right direction.

Thanks

like image 971
Fogmeister Avatar asked Jun 08 '16 16:06

Fogmeister


People also ask

How to handle authentication using alamofire?

There are a few ways to handle authentication using Alamofire, one of them is via Header as shown in the example above, the others are more direct or make use of the URLCredential data type, here are some examples: Alamofire support different ways on how to handle a response.

What is alamofire?

What is Alamofire? Alamofire is an elegant and composable way to interface to HTTP network requests. It builds on top of Apple’s URL Loading System provided by the Foundation framework.

What are HTTP headers in alamofire?

HTTP Headers Alamofire has its own support for HTTP Headers which are a great way to let the client and the server pass additional information with an HTTP request or response. It can be easily added to our Alamofire Request easily by just adding an HTTPHeaders value:

How do I use alamofire with xcworkspace?

Open the file named [projectname.xcworkspace] and your project should have Alamofire installed and ready to go For this example we will be using httpbin.org to simulate our http calls. For starters let’s do a simple GET request, in your ViewController.swift type the following:


2 Answers

OK, after a bit of searching the github and head scratching I decided to create a new response serialiser by extending the Request type.

I created a new saveAuth() block like so...

extension Request {
    public static func AuthSaver() -> ResponseSerializer<Bool, NSError> {
        return ResponseSerializer { request, response, data, error in
            guard error == nil else { return .Failure(error!) }

            if let auth = response?.allHeaderFields["Authorization"] as? String {
                Router.OAuthToken = auth // this uses a didset on the Router to save to keychain
            }

            return .Success(true)
        }
    }

    public func saveAuth() -> Self {
        return response(responseSerializer: Request.AuthSaver()) {_ in}
    }
}

I can call it like...

Alamofire.request(Router.Search(query: query))
    .validate()
    .responseSaveAuth() // this line
    .responseJSON {
        response in
        // ...
}

It still requires adding in each place that I want to strip out the newly sent auth token but it means I can choose when not to do it also and it's a single line of code.

It's maybe not the most elegant code in the extension (I'm still getting to grips with it all) but it makes it much easier to save the authentication each time.

like image 139
Fogmeister Avatar answered Oct 20 '22 10:10

Fogmeister


I have solved this by only having one place in my app that sends network requests. Basically, I have a "network manager" that builds up NSURLRequests and pipes them to one function that actually sends the request (in my case it's an NSOperation sub class). That way I have only one location that I'm reading responses from.

like image 29
Richmond Watkins Avatar answered Oct 20 '22 09:10

Richmond Watkins