-
Notifications
You must be signed in to change notification settings - Fork 2
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
Response error code for actual request is really 401 #1
Comments
For the first concern I came with something like this:
And then use it like this:
|
Hello @annawidera ! class Network: Networking {
let provider: MoyaProvider<MyApp>
let localProvider: MoyaProvider<MyAppLocal>
let xAppUser: XAppUser
let xAppRoutes: XAppRoutes
init(xAppUser: XAppUser, xAppRoutes: XAppRoutes) {
print("INIT NETWORK")
self.xAppUser = xAppUser
self.xAppRoutes = xAppRoutes
let endpointClosure = { (target: MyApp) -> Endpoint<MyApp> in
var targetURL:URL!
targetURL = target.baseURL.appendingPathComponent(xAppRoutes.route(forKey: target.path))
let endpoint: Endpoint<MyApp> = Endpoint<MyApp>(url: targetURL.absoluteString, sampleResponseClosure: {.networkResponse(200, target.sampleData)}, method: target.method, task: target.task, httpHeaderFields: target.headers)
let urlRequest = try! endpoint.urlRequest()
switch target {
case .token(_, _), .refreshToken(_):
let requestBody = urlRequest.httpBody
let authenticationHeader = Network.createAuthenticationHeader(sending: requestBody, forPath: urlRequest.url!.pathWithQuery, method: target.method.rawValue)
return endpoint.adding(newHTTPHeaderFields: ["Authorization": authenticationHeader])
default:
if let token = xAppUser.token {
return endpoint.adding(newHTTPHeaderFields: ["Authorization": "Bearer \(token)"])
} else {
return endpoint
}
}
}
provider = MoyaProvider<MyApp>(endpointClosure: endpointClosure, plugins: (MyAppConstants.debug) ? [NetworkLoggerPlugin(verbose: true)] : [])
localProvider = MoyaProvider<MyAppLocal>(stubClosure: MoyaProvider.immediatelyStub)
}
func request(target: MyApp) -> PrimitiveSequence<SingleTrait, Response> {
print("REQUEST", target)
return provider.rx
.request(target)
.filterSuccessfulStatusCodes()
.retryWhen({ (error: Observable<MoyaError>) in
return error.flatMap({ [unowned self] (error) -> Single<Void> in
if case MoyaError.statusCode(let response) = error {
switch response.statusCode {
case 404:
return self.updateRouteInfo(jwtHeader: target.jwtHeader)
case 401:
guard let refreshToken = self.xAppUser.refreshToken else {
XCGLogger.default.error("Undefined refresh token")
return Single.error(error)
}
return self.provider
.rx.request(.refreshToken(token: refreshToken))
.filterSuccessfulStatusCodes()
.mapObject(Access.self)
.catchError { error in
if case MoyaError.statusCode(let response) = error {
if response.statusCode == 401 || response.statusCode == 400 {
NotificationCenter.default.post(name: .userLogout, object: nil)
}
}
return Single.error(error)
}
.flatMap({ access -> Single<Void> in
self.xAppUser.define(access: access)
return Single.just(())
})
default:
XCGLogger.default.error("Server fatal error")
return Single.error(error)
}
} else {
XCGLogger.default.error("Undefined response error")
return Single.error(error)
}
})
})
}
func request(local target: MyAppLocal) -> PrimitiveSequence<SingleTrait, Response> {
print("REQUEST LOCAL", target)
return localProvider.rx
.request(target)
}
} Than use it in your code: network
.request(target: .posts(group: group.id))
.filterSuccessfulStatusCodes()
.mapArray(Post.self)
.trackActivity(loading) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey Alexandr!
I am trying to implement such behavior like yours: in case request received response "unauthorized", refresh access token and retry the actual request. I had troubles with implementing this and that's how I came across your solution.
I have two concerns which I would like to discuss.
First: I am wondering how do you check if error code for actual request is 401, not for instance 404 (bad path or something).
Second concern is about logout. Are you receiving 401 when attempt to refresh access token failed? Shouldn't it be 400 (according to OAuth2 docs)? Refresh token request is not under authorize protection and if it's failed it's 400 - Bad request with error code: invalid_grant.
https://tools.ietf.org/html/rfc6749#section-5.2
Thank you for any clarification on that topic!
Best!
Ania
The text was updated successfully, but these errors were encountered: