Closed rlam3 closed 7 years ago
The man @colinta always throws around the Ello API as an example. See the networking/
dir for examples: https://github.com/ello/ello-ios/tree/master/Sources/Networking
The real magic is in ElloProvider though.
I've borrowed heavily from it in the past. IMO, the provider set up is all about what your project needs. TargetType
provides enough flexibility that you can request different URLs with the same provider, however, as you mentioned, you might have different requirements for different APIs.
Personally, I set up a provider per API service. In my current project, I created a MyProjectAPI
struct, which manages providers and a singleton instance. The struct has a static method named
request(target: MyProjectAPI.Target, queue: NSOperationQueue, progress: ReactiveMoya.ProgressBlock)
on it. When you invoke something like MyProjectAPI.request(.SignIn(username, password))
, it grabs the default provider, which is configured with a custom endpointClosure
(to add headers/auth fields to the request based on the Target
), and plugins. Since I use ReactiveMoya
, I just added parsing the JSON response as an extension on SignalProducerType
, so my API looks like this:
let target: MyProjectAPI.Target = .SignIn(username, password)
MyProjectAPI.request(target)
.mapSignInResponse()
.flatMap(.Latest) { // Do some work on the mapped response }
The request
method also handles checking the response for errors related to authentication, and will post a notification if the user is not authenticated, to which I respond by kicking the user back to sign in.
Ultimately, the decision is up to you. In the example above, I'm only interacting with a single API, so wrapping it into a single struct seemed best. Ello has a very similar set up. In the Moya example project, you can see that we set up a provider per API service.
@justinmakaila Would love to your take on how to implement Moya with an authentication of using JWT. But prior to firing off each request back to the server, the token is to be checked, and if expired, the token should be refreshed prior to firing off the next request. I know this has something to do with promises, but I'm sure where I can some how do a callback wrapper per request with moya.
Looking at the OAuth approach, I cannot seem to see the connection between how to refresh a token prior to firing off the next request.
I've been trying to follow the Authentication.md documentation from Moya but still have a few question that I need to clear up.
Target
for which we have to seperate Authentication Target and another one for GET/POST a resource Target? Or Do we keep it as one cohesive structure and use the same provider for authentication / fetch resource?let requestClosure = { (endpoint: Endpoint<YourAPI>, done: NSURLRequest -> Void) in
let request = endpoint.urlRequest
YourAwesomeOAuthProvider.signRequest(request, completion: { signedRequest in
// The OAuth provider can make its own network calls to sign your request.
// However, you *must* call `done()` with the signed so that Moya can
// actually send it!
done(signedRequest)
})
}
let provider = MoyaProvider(requestClosure: requestClosure) <<< So is every request with this provider wrapped with request closure to check for token expiration?
Would greatly appreciate it if you could point me to how to refresh an access token prior to firing off another request.
Thanks!
@rlam3 I think that the discussion for difference between endpointClosure
and requestClosure
is moved to #617 so I will take on the next questions:
YourAPI
is in this example is the Target
you use for requests. Let's say you have one Target
in your app and let's call it TwitterAPI
here instead of YourAPI
.YourAwesomeOauthProvider
is just an example. Here you can use third party library to get your token, or you can just use Moya to get it - your choice. There are times you are working with existing SDK's for fetching tokens, but also there might be time that you will need to handle it yourself and Moya can be a perfect fit for it as well. You can even have it in the one TwitterAPI
if you want.provider
, it will first use the requestClosure
to map Endpoint
to NSURLRequest
.Closing this for now. @rlam3, please reopen if you have any additional questions related to this.
When your API grows. It looks like the enum of the Target swift file grows too. Is there a way that this could made more modular?
Is it to use multiple providers as the modular approach when architecting the API routing with Moya? Like a 1 resource per 1 target approach is all I can think of.
But problem arises when a situation like
if checking JSON Web Token
are expired prior firing off an async request. If authentication/JSON Web Token is one resourceTarget and obtaining a resource like user profile is dependent on JSON Web Token. How do we collectively provide enough modularity that both will work together synchronously?I'm not sure if it is be a good idea to use a class based router instead of enums approach.
Or is this it recommended to just use one provider in a large file?
I'm new to Moya. Thanks!