Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about custom interception/retry functionality #155

Closed
jyounus opened this issue Apr 30, 2016 · 9 comments
Closed

Question about custom interception/retry functionality #155

jyounus opened this issue Apr 30, 2016 · 9 comments

Comments

@jyounus
Copy link
Contributor

jyounus commented Apr 30, 2016

Hey there,

I have a specific requirement for my app that I'm working on. The API web service uses JSON Web Tokens. It requires me to pass in a valid x-session-token header for each protected API endpoint.

These session tokens expire every 24h, which means I need to reauthenticate and retry my existing request. Is that currently possible with APIKit? I've seen some PRs about interceptors for version 2.0 but I'm not sure if that's what I need.

Here's an example of what I mean:
Let's say I need to call the GET /user endpoint of my API and it requires me to pass in a valid x-session-token in the header. If the token has expired, I will get an error response, something like this:

success: false, error: {
    code = E1100;
    hint = Token;
    message = "Session token has expired.";
}

Now whenever I get an error response with the error.code == "E1100", what I want to do is, automatically call the POST /authenticate_session endpoint, get the new session token and automatically retry the GET /user request with the updated x-session-token header.

Can you point me in the right direction of how I could best implement this with APIKit?

I'm currently using a different API library for my app and it's proving to be a pain (I'm literally at the point of where I'm trying to fight and go against how the framework was intended to work). Before I start implementing my API logic from scratch, I'm exploring my options and would like to research if I could accomplish this functionality requirement using APIKit (or any other open source library).

Thanks for your help.

@ishkawa
Copy link
Owner

ishkawa commented May 1, 2016

Hi jyounus,

APIKit does not have retry functionality because it aims at providing type-safe single request. IMO, rich functionality for multiple request makes this library complex, so I think combining multiple request is responsibility of developers.

Next, let's think about your use case. To implement auto-retrying, wrapping sendRequest in a subclass is easiest. Here's example of implementation:

class CustomSession: Session {
    override func sendRequest<T: RequestType>(request: T, handler: (Result<T.Response, APIError>) -> Void = {r in}) -> NSURLSessionDataTask? {
        // 1. send request
        return super.sendRequest(request) { [weak self] result in
            // 2. check the error
            if case .Failure(let error) = result where /* check if the error is E1101 */ {
                // 3. refresh token if the error is E1101
                self?.refreshTokenWithHandler { [weak self] refreshedToken in
                    // 4. retry reqeust
                    self?.sendRequest(request, handler: handler)
                }
                return
            }

            handler(result)
        }
    }

    private func refreshTokenWithHandler(handler: String -> Void) {
        ...
    }
}

Note that Session.sharedSession is not a CustomSession.

@jyounus
Copy link
Contributor Author

jyounus commented May 1, 2016

Hey ishkawa,

Thanks for the reply! I will try it out and get back to you if I have any issues.

Regarding Session.sharedSession, any chance you could change "static" into "class" for your variables/methods? In theory, this should allow me to subclass Session and override the sharedSession property.

@ishkawa
Copy link
Owner

ishkawa commented May 3, 2016

Sounds good 👍 I'll work on this tomorrow.

Unlike static property, class property cannot be stored property, so overriding this property will be something like this:

class CustomSession: Session {
    private static var privateSharedSession: Session = ...

    override class var sharedSession: Session {
        return privateSharedSession
    }
}

I expect class property supports stored property in the future version of Swift, because the compiler says:

Class stored properties not yet supported in classes

@jyounus
Copy link
Contributor Author

jyounus commented May 3, 2016

Ah okay, fair enough. No worries, for now I've just duplicated the method and named it something else in my subclass, so it's working fine for me. Obviously not ideal, but that can be improved whenever Swift supports this feature. :)

@ishkawa
Copy link
Owner

ishkawa commented May 4, 2016

This change has been released in 1.4.0!

@jyounus
Copy link
Contributor Author

jyounus commented May 5, 2016

Nice one! I'm currently using your 2.x beta branch, but I will switch to 1.4 and give it a try!

Thanks man, appreciate your efforts on this library! :D

@ishkawa
Copy link
Owner

ishkawa commented May 7, 2016

Shipped 2.x beta 4 yesterday. Now, this change is also available on 2.x branch!

@jyounus
Copy link
Contributor Author

jyounus commented May 7, 2016

Awesome! Thanks :D

@ishkawa ishkawa closed this as completed May 16, 2016
@sensuikan1973
Copy link

sensuikan1973 commented Jun 8, 2018

@ishkawa

How can I implement retry ?
That implement does not work now....

Regards,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants