I'm using Moya to communicate with my API. For many of my endpoints, I require that the user be authenticated (i.e. a bearer token is based in the Authorization header).
In the Moya documentation, here, I found how to include the Authorization header, along with the bearer token.
However, I now need to implement auth token refreshing, and I'm not sure how to do this.
I found this thread on Moya's Github with an answer that looks like it might help, but I have no idea where to put the code. Here is what the answer's code looks like:
// (Endpoint<Target>, NSURLRequest -> Void) -> Void
static func endpointResolver<T>() -> MoyaProvider<T>.RequestClosure where T: TargetType {
return { (endpoint, closure) in
let request = endpoint.urlRequest!
request.httpShouldHandleCookies = false
if (tokenIsOK) {
// Token is valid, so just resume the request and let AccessTokenPlugin set the Authentication header
closure(.success(request))
return
}
// authenticationProvider is a MoyaProvider<Authentication> for example
authenticationProvider.request(.refreshToken(params)) { result in
switch result {
case .success(let response):
self.token = response.mapJSON()["token"]
closure(.success(request)) // This line will "resume" the actual request, and then you can use AccessTokenPlugin to set the Authentication header
case .failure(let error):
closure(.failure(error)) //something went terrible wrong! Request will not be performed
}
}
}
}
And here is my class for my Moya provider:
import Foundation
import Moya
enum ApiService {
case signIn(email: String, password: String)
case like(id: Int, type: String)
}
extension ApiService: TargetType, AccessTokenAuthorizable {
var authorizationType: AuthorizationType {
switch self {
case .signIn(_, _):
return .basic
case .like(_, _):
return .bearer
}
}
var baseURL: URL {
return URL(string: Constants.apiUrl)!
}
var path: String {
switch self {
case .signIn(_, _):
return "user/signin"
case .like(_, _):
return "message/like"
}
}
var method: Moya.Method {
switch self {
case .signIn, .like:
return .post
}
}
var task: Task {
switch self {
case let .signIn(email, password):
return .requestParameters(parameters: ["email": email, "password": password], encoding: JSONEncoding.default)
case let .like(id, type):
return .requestParameters(parameters: ["messageId": id, "type": type], encoding: JSONEncoding.default)
}
}
var sampleData: Data {
return Data()
}
var headers: [String: String]? {
return ["Content-type": "application/json"]
}
}
private extension String {
var urlEscaped: String {
return addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
}
var utf8Encoded: Data {
return data(using: .utf8)!
}
}
Where would I put the answer's code in my code? Am I missing something?