{"action":"created","comment":{"url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/comments/62881136","id":62881136,"diff_hunk":"@@ -159,98 +123,150 @@ public class OAuthSwiftHTTPRequest: NSObject, NSURLSessionDelegate {\n     }\n \n \tpublic func cancel() {\n-\t\ttask?.cancel()\n+        // perform lock here to prevent cancel calls on another thread while creating the request\n+        objc_sync_enter(self)\n+        defer { objc_sync_exit(self) }\n+\n+        // either cancel the request if it's already running or set the flag to prohibit creation of the request\n+        if let task = task {\n+            task.cancel()\n+        } else {\n+            cancelRequested = true\n+        }\n \t}\n \n-    public func makeRequest() throws -> NSMutableURLRequest {\n-        return try OAuthSwiftHTTPRequest.makeRequest(self.URL, method: self.HTTPMethod, headers: self.headers, parameters: self.parameters, dataEncoding: self.dataEncoding, body: self.HTTPBody, paramsLocation: self.paramsLocation)\n-    }\n+}\n \n-    public class func makeRequest(\n-        URL: NSURL,\n-        method: Method,\n-        headers: [String : String],\n-        parameters: Dictionary<String, AnyObject>,\n-        dataEncoding: NSStringEncoding,\n-        body: NSData? = nil,\n-        paramsLocation: ParamsLocation = .AuthorizationHeader) throws -> NSMutableURLRequest {\n-            let request = NSMutableURLRequest(URL: URL)\n-            request.HTTPMethod = method.rawValue\n-            return try setupRequestForOAuth(request,\n-                headers: headers,\n-                parameters: parameters,\n-                dataEncoding: dataEncoding,\n-                body: body,\n-                paramsLocation: paramsLocation\n-            )\n-            \n+// MARK: request preparation\n+\n+extension OAuthSwiftHTTPRequest {\n+\n+    private class func makeRequest(requestConfig: OAuthSwiftHTTPRequestConfig, credentials: OAuthSwiftCredential) throws -> NSMutableURLRequest {\n+        let request = requestConfig.request.mutableCopy() as! NSMutableURLRequest\n+        return try setupRequestForOAuth(request,\n+            additionalParameters: requestConfig.additionalParameters,\n+            dataEncoding: requestConfig.dataEncoding,\n+            paramsLocation: requestConfig.paramsLocation,\n+            credentials: credentials\n+        )\n     }\n \n-    public class func setupRequestForOAuth(request: NSMutableURLRequest,\n-        headers: [String : String],\n-        parameters: Dictionary<String, AnyObject>,\n+    private class func setupRequestForOAuth(request: NSMutableURLRequest,\n+        additionalParameters: Dictionary<String, AnyObject>,\n         dataEncoding: NSStringEncoding,\n-        body: NSData? = nil,\n-        paramsLocation : ParamsLocation = .AuthorizationHeader) throws -> NSMutableURLRequest {\n-            for (key, value) in headers {\n-                request.setValue(value, forHTTPHeaderField: key)\n+        paramsLocation : ParamsLocation = .AuthorizationHeader,\n+        credentials: OAuthSwiftCredential) throws -> NSMutableURLRequest {\n+\n+            // TODO: I think there might be a bug in the handling of the additionalParameters!","path":"OAuthSwift/OAuthSwiftHTTPRequest.swift","position":243,"original_position":243,"commit_id":"95a5211b35c0580606d847c05358be8f084e3dec","original_commit_id":"95a5211b35c0580606d847c05358be8f084e3dec","user":{"login":"phimage","id":8875768,"avatar_url":"https://avatars.githubusercontent.com/u/8875768?v=3","gravatar_id":"","url":"https://api.github.com/users/phimage","html_url":"https://github.com/phimage","followers_url":"https://api.github.com/users/phimage/followers","following_url":"https://api.github.com/users/phimage/following{/other_user}","gists_url":"https://api.github.com/users/phimage/gists{/gist_id}","starred_url":"https://api.github.com/users/phimage/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/phimage/subscriptions","organizations_url":"https://api.github.com/users/phimage/orgs","repos_url":"https://api.github.com/users/phimage/repos","events_url":"https://api.github.com/users/phimage/events{/privacy}","received_events_url":"https://api.github.com/users/phimage/received_events","type":"User","site_admin":false},"body":"Difficult to merge a big PR with many topic (see https://github.com/OAuthSwift/OAuthSwift/blob/master/CONTRIBUTING.md )\r\nThere is no issue referenced with some information about this bug","created_at":"2016-05-11T16:32:17Z","updated_at":"2016-05-11T16:32:17Z","html_url":"https://github.com/OAuthSwift/OAuthSwift/pull/219#discussion_r62881136","pull_request_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/219","_links":{"self":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/comments/62881136"},"html":{"href":"https://github.com/OAuthSwift/OAuthSwift/pull/219#discussion_r62881136"},"pull_request":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/219"}}},"pull_request":{"url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/219","id":65287148,"html_url":"https://github.com/OAuthSwift/OAuthSwift/pull/219","diff_url":"https://github.com/OAuthSwift/OAuthSwift/pull/219.diff","patch_url":"https://github.com/OAuthSwift/OAuthSwift/pull/219.patch","issue_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/issues/219","number":219,"state":"open","locked":false,"title":"Autorenew OAuth2 access tokens","user":{"login":"FGoessler","id":2462969,"avatar_url":"https://avatars.githubusercontent.com/u/2462969?v=3","gravatar_id":"","url":"https://api.github.com/users/FGoessler","html_url":"https://github.com/FGoessler","followers_url":"https://api.github.com/users/FGoessler/followers","following_url":"https://api.github.com/users/FGoessler/following{/other_user}","gists_url":"https://api.github.com/users/FGoessler/gists{/gist_id}","starred_url":"https://api.github.com/users/FGoessler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/FGoessler/subscriptions","organizations_url":"https://api.github.com/users/FGoessler/orgs","repos_url":"https://api.github.com/users/FGoessler/repos","events_url":"https://api.github.com/users/FGoessler/events{/privacy}","received_events_url":"https://api.github.com/users/FGoessler/received_events","type":"User","site_admin":false},"body":"This PR aims to make the access token renewal process transparent to clients of this library as discussed in #217. \r\n\r\nThe implementation differs from my proposed solution in the issue since the token renewal process is to tightly coupled with the ```OAuth2Swift``` class. \r\nNow the ```OAuthSwiftClient``` exposes a callback property which can be set to handle expired/invalid tokens and will retry the request via the completion block. ```OAuth2Swift``` configures this property such that it requests a new access tokens with its refresh token and stores the new token.\r\n\r\nIn case a request failed the error response is checked if the cause is an invalid/expired token. Therefore I created an extension on NSError which I based on the code and specification in the [Wiki](https://github.com/OAuthSwift/OAuthSwift/wiki/OAuth-2.0-Token-Expiration). It also handles special cases for Facebook.\r\n\r\nI would appreciate feedback about the convenience method ```startAuthorizedRequest(...)``` in ```OAuth2Swift``` which was introduced by @fabiomassimo. Since there was no release since this method was added it should be save to remove it, but for now I left it in and marked  it as deprecated.\r\n\r\nThis PR also includes the changes to the unit tests done in #218 since I rebased this branch onto the other. I can perform a rebase on master as soon as the other PR is merged to make the merge and history nicer.","created_at":"2016-04-05T11:14:48Z","updated_at":"2016-05-11T16:32:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d5ffa362ed077acfb581fe8d7f41516f308909f5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/219/commits","review_comments_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/219/comments","review_comment_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/comments{/number}","comments_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/issues/219/comments","statuses_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/statuses/95a5211b35c0580606d847c05358be8f084e3dec","head":{"label":"FGoessler:#217-Autorenew-OAuth2-Tokens","ref":"#217-Autorenew-OAuth2-Tokens","sha":"95a5211b35c0580606d847c05358be8f084e3dec","user":{"login":"FGoessler","id":2462969,"avatar_url":"https://avatars.githubusercontent.com/u/2462969?v=3","gravatar_id":"","url":"https://api.github.com/users/FGoessler","html_url":"https://github.com/FGoessler","followers_url":"https://api.github.com/users/FGoessler/followers","following_url":"https://api.github.com/users/FGoessler/following{/other_user}","gists_url":"https://api.github.com/users/FGoessler/gists{/gist_id}","starred_url":"https://api.github.com/users/FGoessler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/FGoessler/subscriptions","organizations_url":"https://api.github.com/users/FGoessler/orgs","repos_url":"https://api.github.com/users/FGoessler/repos","events_url":"https://api.github.com/users/FGoessler/events{/privacy}","received_events_url":"https://api.github.com/users/FGoessler/received_events","type":"User","site_admin":false},"repo":{"id":55257979,"name":"OAuthSwift","full_name":"FGoessler/OAuthSwift","owner":{"login":"FGoessler","id":2462969,"avatar_url":"https://avatars.githubusercontent.com/u/2462969?v=3","gravatar_id":"","url":"https://api.github.com/users/FGoessler","html_url":"https://github.com/FGoessler","followers_url":"https://api.github.com/users/FGoessler/followers","following_url":"https://api.github.com/users/FGoessler/following{/other_user}","gists_url":"https://api.github.com/users/FGoessler/gists{/gist_id}","starred_url":"https://api.github.com/users/FGoessler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/FGoessler/subscriptions","organizations_url":"https://api.github.com/users/FGoessler/orgs","repos_url":"https://api.github.com/users/FGoessler/repos","events_url":"https://api.github.com/users/FGoessler/events{/privacy}","received_events_url":"https://api.github.com/users/FGoessler/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/FGoessler/OAuthSwift","description":"Swift based OAuth library for iOS","fork":true,"url":"https://api.github.com/repos/FGoessler/OAuthSwift","forks_url":"https://api.github.com/repos/FGoessler/OAuthSwift/forks","keys_url":"https://api.github.com/repos/FGoessler/OAuthSwift/keys{/key_id}","collaborators_url":"https://api.github.com/repos/FGoessler/OAuthSwift/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/FGoessler/OAuthSwift/teams","hooks_url":"https://api.github.com/repos/FGoessler/OAuthSwift/hooks","issue_events_url":"https://api.github.com/repos/FGoessler/OAuthSwift/issues/events{/number}","events_url":"https://api.github.com/repos/FGoessler/OAuthSwift/events","assignees_url":"https://api.github.com/repos/FGoessler/OAuthSwift/assignees{/user}","branches_url":"https://api.github.com/repos/FGoessler/OAuthSwift/branches{/branch}","tags_url":"https://api.github.com/repos/FGoessler/OAuthSwift/tags","blobs_url":"https://api.github.com/repos/FGoessler/OAuthSwift/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/FGoessler/OAuthSwift/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/FGoessler/OAuthSwift/git/refs{/sha}","trees_url":"https://api.github.com/repos/FGoessler/OAuthSwift/git/trees{/sha}","statuses_url":"https://api.github.com/repos/FGoessler/OAuthSwift/statuses/{sha}","languages_url":"https://api.github.com/repos/FGoessler/OAuthSwift/languages","stargazers_url":"https://api.github.com/repos/FGoessler/OAuthSwift/stargazers","contributors_url":"https://api.github.com/repos/FGoessler/OAuthSwift/contributors","subscribers_url":"https://api.github.com/repos/FGoessler/OAuthSwift/subscribers","subscription_url":"https://api.github.com/repos/FGoessler/OAuthSwift/subscription","commits_url":"https://api.github.com/repos/FGoessler/OAuthSwift/commits{/sha}","git_commits_url":"https://api.github.com/repos/FGoessler/OAuthSwift/git/commits{/sha}","comments_url":"https://api.github.com/repos/FGoessler/OAuthSwift/comments{/number}","issue_comment_url":"https://api.github.com/repos/FGoessler/OAuthSwift/issues/comments{/number}","contents_url":"https://api.github.com/repos/FGoessler/OAuthSwift/contents/{+path}","compare_url":"https://api.github.com/repos/FGoessler/OAuthSwift/compare/{base}...{head}","merges_url":"https://api.github.com/repos/FGoessler/OAuthSwift/merges","archive_url":"https://api.github.com/repos/FGoessler/OAuthSwift/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/FGoessler/OAuthSwift/downloads","issues_url":"https://api.github.com/repos/FGoessler/OAuthSwift/issues{/number}","pulls_url":"https://api.github.com/repos/FGoessler/OAuthSwift/pulls{/number}","milestones_url":"https://api.github.com/repos/FGoessler/OAuthSwift/milestones{/number}","notifications_url":"https://api.github.com/repos/FGoessler/OAuthSwift/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/FGoessler/OAuthSwift/labels{/name}","releases_url":"https://api.github.com/repos/FGoessler/OAuthSwift/releases{/id}","deployments_url":"https://api.github.com/repos/FGoessler/OAuthSwift/deployments","created_at":"2016-04-01T19:42:39Z","updated_at":"2016-04-01T19:42:41Z","pushed_at":"2016-05-04T12:23:54Z","git_url":"git://github.com/FGoessler/OAuthSwift.git","ssh_url":"git@github.com:FGoessler/OAuthSwift.git","clone_url":"https://github.com/FGoessler/OAuthSwift.git","svn_url":"https://github.com/FGoessler/OAuthSwift","homepage":"","size":2882,"stargazers_count":0,"watchers_count":0,"language":"Swift","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"OAuthSwift:master","ref":"master","sha":"2f180840ca01b6c7d13f4d79661de78dc12d902f","user":{"login":"OAuthSwift","id":16102305,"avatar_url":"https://avatars.githubusercontent.com/u/16102305?v=3","gravatar_id":"","url":"https://api.github.com/users/OAuthSwift","html_url":"https://github.com/OAuthSwift","followers_url":"https://api.github.com/users/OAuthSwift/followers","following_url":"https://api.github.com/users/OAuthSwift/following{/other_user}","gists_url":"https://api.github.com/users/OAuthSwift/gists{/gist_id}","starred_url":"https://api.github.com/users/OAuthSwift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OAuthSwift/subscriptions","organizations_url":"https://api.github.com/users/OAuthSwift/orgs","repos_url":"https://api.github.com/users/OAuthSwift/repos","events_url":"https://api.github.com/users/OAuthSwift/events{/privacy}","received_events_url":"https://api.github.com/users/OAuthSwift/received_events","type":"Organization","site_admin":false},"repo":{"id":21315049,"name":"OAuthSwift","full_name":"OAuthSwift/OAuthSwift","owner":{"login":"OAuthSwift","id":16102305,"avatar_url":"https://avatars.githubusercontent.com/u/16102305?v=3","gravatar_id":"","url":"https://api.github.com/users/OAuthSwift","html_url":"https://github.com/OAuthSwift","followers_url":"https://api.github.com/users/OAuthSwift/followers","following_url":"https://api.github.com/users/OAuthSwift/following{/other_user}","gists_url":"https://api.github.com/users/OAuthSwift/gists{/gist_id}","starred_url":"https://api.github.com/users/OAuthSwift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OAuthSwift/subscriptions","organizations_url":"https://api.github.com/users/OAuthSwift/orgs","repos_url":"https://api.github.com/users/OAuthSwift/repos","events_url":"https://api.github.com/users/OAuthSwift/events{/privacy}","received_events_url":"https://api.github.com/users/OAuthSwift/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/OAuthSwift/OAuthSwift","description":"Swift based OAuth library for iOS","fork":false,"url":"https://api.github.com/repos/OAuthSwift/OAuthSwift","forks_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/forks","keys_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/teams","hooks_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/hooks","issue_events_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/issues/events{/number}","events_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/events","assignees_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/assignees{/user}","branches_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/branches{/branch}","tags_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/tags","blobs_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/git/refs{/sha}","trees_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/statuses/{sha}","languages_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/languages","stargazers_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/stargazers","contributors_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/contributors","subscribers_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/subscribers","subscription_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/subscription","commits_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/commits{/sha}","git_commits_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/git/commits{/sha}","comments_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/comments{/number}","issue_comment_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/issues/comments{/number}","contents_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/contents/{+path}","compare_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/merges","archive_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/downloads","issues_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/issues{/number}","pulls_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls{/number}","milestones_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/milestones{/number}","notifications_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/labels{/name}","releases_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/releases{/id}","deployments_url":"https://api.github.com/repos/OAuthSwift/OAuthSwift/deployments","created_at":"2014-06-29T02:27:16Z","updated_at":"2016-05-09T12:06:45Z","pushed_at":"2016-05-04T12:23:55Z","git_url":"git://github.com/OAuthSwift/OAuthSwift.git","ssh_url":"git@github.com:OAuthSwift/OAuthSwift.git","clone_url":"https://github.com/OAuthSwift/OAuthSwift.git","svn_url":"https://github.com/OAuthSwift/OAuthSwift","homepage":"","size":3046,"stargazers_count":1111,"watchers_count":1111,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":211,"mirror_url":null,"open_issues_count":8,"forks":211,"open_issues":8,"watchers":1111,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/219"},"html":{"href":"https://github.com/OAuthSwift/OAuthSwift/pull/219"},"issue":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/issues/219"},"comments":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/issues/219/comments"},"review_comments":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/219/comments"},"review_comment":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/pulls/219/commits"},"statuses":{"href":"https://api.github.com/repos/OAuthSwift/OAuthSwift/statuses/95a5211b35c0580606d847c05358be8f084e3dec"}}}}