{"action":"created","issue":{"url":"https://api.github.com/repos/Moya/Moya/issues/813","repository_url":"https://api.github.com/repos/Moya/Moya","labels_url":"https://api.github.com/repos/Moya/Moya/issues/813/labels{/name}","comments_url":"https://api.github.com/repos/Moya/Moya/issues/813/comments","events_url":"https://api.github.com/repos/Moya/Moya/issues/813/events","html_url":"https://github.com/Moya/Moya/pull/813","id":192764406,"number":813,"title":"Allow plugins to modify requests and responses.","user":{"login":"scottrhoyt","id":4259250,"avatar_url":"https://avatars.githubusercontent.com/u/4259250?v=3","gravatar_id":"","url":"https://api.github.com/users/scottrhoyt","html_url":"https://github.com/scottrhoyt","followers_url":"https://api.github.com/users/scottrhoyt/followers","following_url":"https://api.github.com/users/scottrhoyt/following{/other_user}","gists_url":"https://api.github.com/users/scottrhoyt/gists{/gist_id}","starred_url":"https://api.github.com/users/scottrhoyt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scottrhoyt/subscriptions","organizations_url":"https://api.github.com/users/scottrhoyt/orgs","repos_url":"https://api.github.com/users/scottrhoyt/repos","events_url":"https://api.github.com/users/scottrhoyt/events{/privacy}","received_events_url":"https://api.github.com/users/scottrhoyt/received_events","type":"User","site_admin":false},"labels":[{"id":122272859,"url":"https://api.github.com/repos/Moya/Moya/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":16,"created_at":"2016-12-01T06:27:07Z","updated_at":"2016-12-02T20:29:50Z","closed_at":"2016-12-02T20:29:42Z","pull_request":{"url":"https://api.github.com/repos/Moya/Moya/pulls/813","html_url":"https://github.com/Moya/Moya/pull/813","diff_url":"https://github.com/Moya/Moya/pull/813.diff","patch_url":"https://github.com/Moya/Moya/pull/813.patch"},"body":"## Purpose\r\n\r\nWhile the endpoint and request closures are useful for modifying requests, they\r\nprovide an inconvenient solution for many use cases--notably authentication--for\r\na number of reasons:\r\n  * Only one closure of each type can be provided, making it less ideal when\r\n    multiple atomic modifications need to be made to a request.\r\n  * Overriding these closures require duplicating the work that the default\r\n    closures do and knowledge of more internal Moya API.\r\n  * It is sometimes ambiguous as to which closure you should choose for your\r\n    task.\r\n\r\n## Solution\r\n\r\nPlugins can be extended with ability to modify requests and results. This would\r\nbring the concept more in line with the concept of web framework middleware and\r\nprovide a convenient interface for Moya users and 3rd party plugin creators.\r\nUltimately, the ability to interact with requests and responses will make\r\nPlugins much more useful.\r\n\r\nTo do this, we can add two functions to `PluginType`:\r\n```swift\r\nfunc prepareRequest(_ request: URLRequest, target: TargetType) -> URLRequest\r\nfunc processResponse(_ result: Result<Response, Error>, target: TargetType) -> Result<Response, Error>\r\n```\r\n\r\n*Note: function names were chosen to be consistent with existing interface but\r\nthere is an opportunity to better conform to the Swift API Guidelines*\r\n\r\nThese functions are called before `willSendRequest` and after `didReceiveResponse`\r\nrespectively. Like the other protocol functions, empty implementations are\r\nprovided by default.\r\n\r\n## Example\r\n\r\nThe following is an example of supplying an access token via a plugin and only\r\nauthorizing targets that need it.\r\n\r\n```swift\r\nprotocol AuthorizedTargetType: TargetType {\r\n  var needsAuth: Bool { get }\r\n}\r\n\r\nstruct AuthPlugin: PluginType {\r\n  let token: String\r\n\r\n  func prepareRequest(_ request: URLRequest, target: TargetType) -> URLRequest {\r\n    guard let target = target as? AuthorizedTargetType, target.needsAuth else {\r\n      return request\r\n    }\r\n\r\n    var request = request\r\n    request.addValue(\"Bearer \" + token, forHTTPHeaderField: \"Authorization\")\r\n    return request\r\n  }\r\n}\r\n\r\nlet provider = MoyaProvider<Target>(\r\n  plugins: [\r\n    AuthPlugin(token: \"eyeAm.AJsoN.weBTOKen\"),\r\n    NetworkLoggerPlugin()\r\n  ]\r\n)\r\n```\r\n\r\n## Alternatives Considered\r\n\r\n### *Add another closure for simpler request modification*\r\n\r\nWhile this would solve the problem of request modification not being\r\nstraightforward, it still wouldn't be clean to chain modifications together.\r\nAlso, there wouldn't be a simple interface to encourage 3rd party plugin creation.\r\n\r\n### *Make the existing plugin functions capable of modifying request/results*\r\n\r\nThis would not be easily possible due to the way the `willSendRequest` abstracts\r\nAlamofire's `Request`. In addition, adding the extra lifecycle calls makes it\r\neasier to create consistent behavior (e.g. always log requests after they have\r\nbeen modified by plugins).\r\n"},"comment":{"url":"https://api.github.com/repos/Moya/Moya/issues/comments/264554934","html_url":"https://github.com/Moya/Moya/pull/813#issuecomment-264554934","issue_url":"https://api.github.com/repos/Moya/Moya/issues/813","id":264554934,"user":{"login":"ashfurrow","id":498212,"avatar_url":"https://avatars.githubusercontent.com/u/498212?v=3","gravatar_id":"","url":"https://api.github.com/users/ashfurrow","html_url":"https://github.com/ashfurrow","followers_url":"https://api.github.com/users/ashfurrow/followers","following_url":"https://api.github.com/users/ashfurrow/following{/other_user}","gists_url":"https://api.github.com/users/ashfurrow/gists{/gist_id}","starred_url":"https://api.github.com/users/ashfurrow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ashfurrow/subscriptions","organizations_url":"https://api.github.com/users/ashfurrow/orgs","repos_url":"https://api.github.com/users/ashfurrow/repos","events_url":"https://api.github.com/users/ashfurrow/events{/privacy}","received_events_url":"https://api.github.com/users/ashfurrow/received_events","type":"User","site_admin":false},"created_at":"2016-12-02T20:29:50Z","updated_at":"2016-12-02T20:29:50Z","body":"Thanks a lot for contributing to Moya! I've invited you to join the Moya GitHub organization – no pressure to accept! If you'd like more information on what that means, check out our [contributor guidelines](https://github.com/Moya/contributors) and feel free to reach out with any questions."}}
{"actor":{"display_login":"ashfurrow"}}