{"action":"created","issue":{"url":"https://api.github.com/repos/Alamofire/Alamofire/issues/2517","repository_url":"https://api.github.com/repos/Alamofire/Alamofire","labels_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/2517/labels{/name}","comments_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/2517/comments","events_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/2517/events","html_url":"https://github.com/Alamofire/Alamofire/issues/2517","id":323354429,"node_id":"MDU6SXNzdWUzMjMzNTQ0Mjk=","number":2517,"title":"Feature request: ability to change the request asynchronously in the RequestAdapter","user":{"login":"ricardopereira","id":3541185,"node_id":"MDQ6VXNlcjM1NDExODU=","avatar_url":"https://avatars1.githubusercontent.com/u/3541185?v=4","gravatar_id":"","url":"https://api.github.com/users/ricardopereira","html_url":"https://github.com/ricardopereira","followers_url":"https://api.github.com/users/ricardopereira/followers","following_url":"https://api.github.com/users/ricardopereira/following{/other_user}","gists_url":"https://api.github.com/users/ricardopereira/gists{/gist_id}","starred_url":"https://api.github.com/users/ricardopereira/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ricardopereira/subscriptions","organizations_url":"https://api.github.com/users/ricardopereira/orgs","repos_url":"https://api.github.com/users/ricardopereira/repos","events_url":"https://api.github.com/users/ricardopereira/events{/privacy}","received_events_url":"https://api.github.com/users/ricardopereira/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-05-15T19:36:54Z","updated_at":"2018-08-08T02:12:42Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"* [x] I've read, understood, and done my best to follow the [*CONTRIBUTING guidelines](https://github.com/Alamofire/Alamofire/blob/master/CONTRIBUTING.md).\r\n\r\n## What did you do?\r\n\r\nAs I mentioned [here](https://github.com/Alamofire/Alamofire/pull/1450#issuecomment-389277756), I want to request a new access token in my `RequestAdapter` implementation when the token has expired. I know in advance when will the access token expire so, I think it would be nice to spare a request that will probably answer with a 401.\r\n\r\n## What did you expect to happen?\r\n\r\nI was expecting something like:\r\n\r\n```swift\r\ntypealias RequestAdaptCompletion = (_ urlRequest: URLRequest) -> Void\r\n\r\nfunc adapt(_ urlRequest: URLRequest, completion: @escaping RequestAdaptCompletion) throws {\r\n    if userTokenDetails.expires.timeIntervalSince(userTokenDetails.issued) <= 0 {\r\n        reauthorize { newUserTokenDetails in\r\n            urlRequest.setValue(\"Bearer \" + newUserTokenDetails.accessToken, forHTTPHeaderField: \"Authorization\")\r\n            completion(urlRequest)\r\n        }\r\n    }\r\n    else {\r\n        completion(urlRequest)\r\n    }\r\n}\r\n```\r\n\r\n> @ricardopereira It would be much easier to just allow adapter errors to trigger retry behavior. I'm not sure if that would work now, but it might become possible for Alamofire 5. Such a feature likely wouldn't ship until then anyway.\r\n\r\nbut as @jshier mentioned in #1450, maybe triggering an error in the Adapter and call retry should be enough (at least for my case 😅).\r\n\r\n**UPDATE:**\r\n\r\nMessage from @cnoon:\r\n\r\n> This can actually already be done on AF4.x. I know b/c we're doing it in our internal Nike networking library.\r\n>\r\n>**How?**\r\n>\r\n>We throw custom AdaptError types tailored to our use cases. For example, we have .missingCredential, .expiredCredential, and I believe one other case that we'll throw from adapt. Then in retry, we inspect the error to see if it was an AdaptError. If it was .expired, then we know we need to refresh. This allows us to avoid making the initial request with a credential we already know is expired.\r\n\r\n## Alamofire Environment\r\n\r\n**Alamofire version:** 4.7.2\r\n**Xcode version:** 9.3.1\r\n**Swift version:** 4.0\r\n**Platform(s) running Alamofire:** iOS\r\n**macOS version running Xcode:** High Sierra 10.13.4 (17E202)\r\n\r\n## Demo Project\r\n\r\nNo demo but I can arrange something if needed.\r\n\r\n🤩 Thank you for your amazing work!"},"comment":{"url":"https://api.github.com/repos/Alamofire/Alamofire/issues/comments/411260790","html_url":"https://github.com/Alamofire/Alamofire/issues/2517#issuecomment-411260790","issue_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/2517","id":411260790,"node_id":"MDEyOklzc3VlQ29tbWVudDQxMTI2MDc5MA==","user":{"login":"FrancoSabadini","id":5099645,"node_id":"MDQ6VXNlcjUwOTk2NDU=","avatar_url":"https://avatars1.githubusercontent.com/u/5099645?v=4","gravatar_id":"","url":"https://api.github.com/users/FrancoSabadini","html_url":"https://github.com/FrancoSabadini","followers_url":"https://api.github.com/users/FrancoSabadini/followers","following_url":"https://api.github.com/users/FrancoSabadini/following{/other_user}","gists_url":"https://api.github.com/users/FrancoSabadini/gists{/gist_id}","starred_url":"https://api.github.com/users/FrancoSabadini/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/FrancoSabadini/subscriptions","organizations_url":"https://api.github.com/users/FrancoSabadini/orgs","repos_url":"https://api.github.com/users/FrancoSabadini/repos","events_url":"https://api.github.com/users/FrancoSabadini/events{/privacy}","received_events_url":"https://api.github.com/users/FrancoSabadini/received_events","type":"User","site_admin":false},"created_at":"2018-08-08T02:12:42Z","updated_at":"2018-08-08T02:12:42Z","author_association":"NONE","body":"Another case to make for this is that sometimes we are using 3rd party libraries for authorization which only provide async methods to get the access token (e.g., Firebase) and we can't use the `RequestAdapter` to add the access token to all the requests, nor can we change the third party library APIs. This feature would be great for this."}}
{"actor":{"display_login":"FrancoSabadini"}}