{"action":"created","comment":{"url":"https://api.github.com/repos/falconry/falcon/pulls/comments/27180925","id":27180925,"diff_hunk":"@@ -136,6 +145,82 @@ def set_stream(self, stream, stream_len):\n         self.stream = stream\n         self.stream_len = stream_len\n \n+    def set_cookie(self, name, value, expires=None, max_age=None,\n+                   domain=None, path=None, secure=True, httponly=True):\n+        \"\"\"Set a response cookie.\n+\n+        Args:\n+            name (str):\n+                Cookie name\n+            value (str):\n+                Cookie value\n+            expires (datetime): Defines when the cookie should expire.\n+                the default is to expire when the browser is closed.\n+            max_age (int): The Max-Age attribute defines the lifetime of the\n+                cookie, in seconds.  The delta-seconds value is a decimal non-\n+                negative integer.  After delta-seconds seconds elapse,\n+                the client should discard the cookie.\n+            domain (str): The Domain attribute specifies the domain for\n+                which the cookie is valid.\n+                An explicitly specified domain must always start with a dot.\n+                A value of 0 means the cookie should be discarded immediately.\n+            path (str): The Path attribute specifies the subset of URLs to\n+                which this cookie applies.\n+            secure (bool) (default: True): The Secure attribute directs the","path":"falcon/response.py","position":59,"original_position":59,"commit_id":"a0a7870078f3f82c7918d5c62511aebdd83f8e3e","original_commit_id":"a0a7870078f3f82c7918d5c62511aebdd83f8e3e","user":{"login":"kgriffs","id":719939,"avatar_url":"https://avatars.githubusercontent.com/u/719939?v=3","gravatar_id":"","url":"https://api.github.com/users/kgriffs","html_url":"https://github.com/kgriffs","followers_url":"https://api.github.com/users/kgriffs/followers","following_url":"https://api.github.com/users/kgriffs/following{/other_user}","gists_url":"https://api.github.com/users/kgriffs/gists{/gist_id}","starred_url":"https://api.github.com/users/kgriffs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kgriffs/subscriptions","organizations_url":"https://api.github.com/users/kgriffs/orgs","repos_url":"https://api.github.com/users/kgriffs/repos","events_url":"https://api.github.com/users/kgriffs/events{/privacy}","received_events_url":"https://api.github.com/users/kgriffs/received_events","type":"User","site_admin":false},"body":"Might be worth adding a warning here that HTTPS should be forced when using secure cookies, using a combination of HSTS, web server config, and checking at the app layer. Falcon could check for HTTPS and refuse to return a secure cookie if the transport is not secure, but then we'd have to provide a way for people to turn that off in dev environments since you typically don't bother to set up TLS in that case. Probably not worth it right now, but something to consider for the future...\r\n\r\nSee also: #460.","created_at":"2015-03-26T00:49:21Z","updated_at":"2015-03-26T00:49:21Z","html_url":"https://github.com/falconry/falcon/pull/405#discussion_r27180925","pull_request_url":"https://api.github.com/repos/falconry/falcon/pulls/405","_links":{"self":{"href":"https://api.github.com/repos/falconry/falcon/pulls/comments/27180925"},"html":{"href":"https://github.com/falconry/falcon/pull/405#discussion_r27180925"},"pull_request":{"href":"https://api.github.com/repos/falconry/falcon/pulls/405"}}},"pull_request":{"url":"https://api.github.com/repos/falconry/falcon/pulls/405","id":26995876,"html_url":"https://github.com/falconry/falcon/pull/405","diff_url":"https://github.com/falconry/falcon/pull/405.diff","patch_url":"https://github.com/falconry/falcon/pull/405.patch","issue_url":"https://api.github.com/repos/falconry/falcon/issues/405","number":405,"state":"open","locked":false,"title":"feat(Response) Add cookie helpers","user":{"login":"tbug","id":195468,"avatar_url":"https://avatars.githubusercontent.com/u/195468?v=3","gravatar_id":"","url":"https://api.github.com/users/tbug","html_url":"https://github.com/tbug","followers_url":"https://api.github.com/users/tbug/followers","following_url":"https://api.github.com/users/tbug/following{/other_user}","gists_url":"https://api.github.com/users/tbug/gists{/gist_id}","starred_url":"https://api.github.com/users/tbug/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tbug/subscriptions","organizations_url":"https://api.github.com/users/tbug/orgs","repos_url":"https://api.github.com/users/tbug/repos","events_url":"https://api.github.com/users/tbug/events{/privacy}","received_events_url":"https://api.github.com/users/tbug/received_events","type":"User","site_admin":false},"body":"Add the following new helpers for setting and getting cookies\r\n\r\n- `set_cookie(name : str, value : str, **cookie_params) -> None`\r\n- `get_cookie(name : str) -> Morsel`\r\n- ` get_cookies() -> List[Morsel]`\r\n- `unset_cookie(name : str) -> None`\r\n\r\nCookies will - if set - be rendered and merged with headers in\r\n_wsgi_headers. For responses that don't use cookies, there will\r\nno performance hit, except for a single \"if cookies is not None:\"\r\ncheck in the _wsgi_headers call.\r\nImplementation use the http.cookies.SimpleCookie (py3) or\r\nCookie.SimpleCookie (py2) from the stdlib.\r\nMight find extra speed in doing our own implementation.\r\n\r\nFixes #292","created_at":"2015-01-07T23:14:27Z","updated_at":"2015-03-26T00:49:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1e10537ce75ea0fc29babfb27e30b8558a5ae5f4","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/falconry/falcon/pulls/405/commits","review_comments_url":"https://api.github.com/repos/falconry/falcon/pulls/405/comments","review_comment_url":"https://api.github.com/repos/falconry/falcon/pulls/comments{/number}","comments_url":"https://api.github.com/repos/falconry/falcon/issues/405/comments","statuses_url":"https://api.github.com/repos/falconry/falcon/statuses/a0a7870078f3f82c7918d5c62511aebdd83f8e3e","head":{"label":"tbug:feature/cookiehelpers","ref":"feature/cookiehelpers","sha":"a0a7870078f3f82c7918d5c62511aebdd83f8e3e","user":{"login":"tbug","id":195468,"avatar_url":"https://avatars.githubusercontent.com/u/195468?v=3","gravatar_id":"","url":"https://api.github.com/users/tbug","html_url":"https://github.com/tbug","followers_url":"https://api.github.com/users/tbug/followers","following_url":"https://api.github.com/users/tbug/following{/other_user}","gists_url":"https://api.github.com/users/tbug/gists{/gist_id}","starred_url":"https://api.github.com/users/tbug/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tbug/subscriptions","organizations_url":"https://api.github.com/users/tbug/orgs","repos_url":"https://api.github.com/users/tbug/repos","events_url":"https://api.github.com/users/tbug/events{/privacy}","received_events_url":"https://api.github.com/users/tbug/received_events","type":"User","site_admin":false},"repo":{"id":26658808,"name":"falcon","full_name":"tbug/falcon","owner":{"login":"tbug","id":195468,"avatar_url":"https://avatars.githubusercontent.com/u/195468?v=3","gravatar_id":"","url":"https://api.github.com/users/tbug","html_url":"https://github.com/tbug","followers_url":"https://api.github.com/users/tbug/followers","following_url":"https://api.github.com/users/tbug/following{/other_user}","gists_url":"https://api.github.com/users/tbug/gists{/gist_id}","starred_url":"https://api.github.com/users/tbug/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tbug/subscriptions","organizations_url":"https://api.github.com/users/tbug/orgs","repos_url":"https://api.github.com/users/tbug/repos","events_url":"https://api.github.com/users/tbug/events{/privacy}","received_events_url":"https://api.github.com/users/tbug/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tbug/falcon","description":"Falcon is a high-performance Python framework for building cloud APIs and web app backends.","fork":true,"url":"https://api.github.com/repos/tbug/falcon","forks_url":"https://api.github.com/repos/tbug/falcon/forks","keys_url":"https://api.github.com/repos/tbug/falcon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tbug/falcon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tbug/falcon/teams","hooks_url":"https://api.github.com/repos/tbug/falcon/hooks","issue_events_url":"https://api.github.com/repos/tbug/falcon/issues/events{/number}","events_url":"https://api.github.com/repos/tbug/falcon/events","assignees_url":"https://api.github.com/repos/tbug/falcon/assignees{/user}","branches_url":"https://api.github.com/repos/tbug/falcon/branches{/branch}","tags_url":"https://api.github.com/repos/tbug/falcon/tags","blobs_url":"https://api.github.com/repos/tbug/falcon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tbug/falcon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tbug/falcon/git/refs{/sha}","trees_url":"https://api.github.com/repos/tbug/falcon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tbug/falcon/statuses/{sha}","languages_url":"https://api.github.com/repos/tbug/falcon/languages","stargazers_url":"https://api.github.com/repos/tbug/falcon/stargazers","contributors_url":"https://api.github.com/repos/tbug/falcon/contributors","subscribers_url":"https://api.github.com/repos/tbug/falcon/subscribers","subscription_url":"https://api.github.com/repos/tbug/falcon/subscription","commits_url":"https://api.github.com/repos/tbug/falcon/commits{/sha}","git_commits_url":"https://api.github.com/repos/tbug/falcon/git/commits{/sha}","comments_url":"https://api.github.com/repos/tbug/falcon/comments{/number}","issue_comment_url":"https://api.github.com/repos/tbug/falcon/issues/comments{/number}","contents_url":"https://api.github.com/repos/tbug/falcon/contents/{+path}","compare_url":"https://api.github.com/repos/tbug/falcon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tbug/falcon/merges","archive_url":"https://api.github.com/repos/tbug/falcon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tbug/falcon/downloads","issues_url":"https://api.github.com/repos/tbug/falcon/issues{/number}","pulls_url":"https://api.github.com/repos/tbug/falcon/pulls{/number}","milestones_url":"https://api.github.com/repos/tbug/falcon/milestones{/number}","notifications_url":"https://api.github.com/repos/tbug/falcon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tbug/falcon/labels{/name}","releases_url":"https://api.github.com/repos/tbug/falcon/releases{/id}","created_at":"2014-11-14T21:42:55Z","updated_at":"2015-02-10T20:19:46Z","pushed_at":"2015-02-11T21:05:10Z","git_url":"git://github.com/tbug/falcon.git","ssh_url":"git@github.com:tbug/falcon.git","clone_url":"https://github.com/tbug/falcon.git","svn_url":"https://github.com/tbug/falcon","homepage":"http://falconframework.org","size":5595,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"falconry:master","ref":"master","sha":"0f1ef875fb5037533da1e4d07a24e1a447602a43","user":{"login":"falconry","id":11353642,"avatar_url":"https://avatars.githubusercontent.com/u/11353642?v=3","gravatar_id":"","url":"https://api.github.com/users/falconry","html_url":"https://github.com/falconry","followers_url":"https://api.github.com/users/falconry/followers","following_url":"https://api.github.com/users/falconry/following{/other_user}","gists_url":"https://api.github.com/users/falconry/gists{/gist_id}","starred_url":"https://api.github.com/users/falconry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/falconry/subscriptions","organizations_url":"https://api.github.com/users/falconry/orgs","repos_url":"https://api.github.com/users/falconry/repos","events_url":"https://api.github.com/users/falconry/events{/privacy}","received_events_url":"https://api.github.com/users/falconry/received_events","type":"Organization","site_admin":false},"repo":{"id":7040500,"name":"falcon","full_name":"falconry/falcon","owner":{"login":"falconry","id":11353642,"avatar_url":"https://avatars.githubusercontent.com/u/11353642?v=3","gravatar_id":"","url":"https://api.github.com/users/falconry","html_url":"https://github.com/falconry","followers_url":"https://api.github.com/users/falconry/followers","following_url":"https://api.github.com/users/falconry/following{/other_user}","gists_url":"https://api.github.com/users/falconry/gists{/gist_id}","starred_url":"https://api.github.com/users/falconry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/falconry/subscriptions","organizations_url":"https://api.github.com/users/falconry/orgs","repos_url":"https://api.github.com/users/falconry/repos","events_url":"https://api.github.com/users/falconry/events{/privacy}","received_events_url":"https://api.github.com/users/falconry/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/falconry/falcon","description":"Falcon is a high-performance Python framework for building cloud APIs and web app backends.","fork":false,"url":"https://api.github.com/repos/falconry/falcon","forks_url":"https://api.github.com/repos/falconry/falcon/forks","keys_url":"https://api.github.com/repos/falconry/falcon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/falconry/falcon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/falconry/falcon/teams","hooks_url":"https://api.github.com/repos/falconry/falcon/hooks","issue_events_url":"https://api.github.com/repos/falconry/falcon/issues/events{/number}","events_url":"https://api.github.com/repos/falconry/falcon/events","assignees_url":"https://api.github.com/repos/falconry/falcon/assignees{/user}","branches_url":"https://api.github.com/repos/falconry/falcon/branches{/branch}","tags_url":"https://api.github.com/repos/falconry/falcon/tags","blobs_url":"https://api.github.com/repos/falconry/falcon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/falconry/falcon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/falconry/falcon/git/refs{/sha}","trees_url":"https://api.github.com/repos/falconry/falcon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/falconry/falcon/statuses/{sha}","languages_url":"https://api.github.com/repos/falconry/falcon/languages","stargazers_url":"https://api.github.com/repos/falconry/falcon/stargazers","contributors_url":"https://api.github.com/repos/falconry/falcon/contributors","subscribers_url":"https://api.github.com/repos/falconry/falcon/subscribers","subscription_url":"https://api.github.com/repos/falconry/falcon/subscription","commits_url":"https://api.github.com/repos/falconry/falcon/commits{/sha}","git_commits_url":"https://api.github.com/repos/falconry/falcon/git/commits{/sha}","comments_url":"https://api.github.com/repos/falconry/falcon/comments{/number}","issue_comment_url":"https://api.github.com/repos/falconry/falcon/issues/comments{/number}","contents_url":"https://api.github.com/repos/falconry/falcon/contents/{+path}","compare_url":"https://api.github.com/repos/falconry/falcon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/falconry/falcon/merges","archive_url":"https://api.github.com/repos/falconry/falcon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/falconry/falcon/downloads","issues_url":"https://api.github.com/repos/falconry/falcon/issues{/number}","pulls_url":"https://api.github.com/repos/falconry/falcon/pulls{/number}","milestones_url":"https://api.github.com/repos/falconry/falcon/milestones{/number}","notifications_url":"https://api.github.com/repos/falconry/falcon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/falconry/falcon/labels{/name}","releases_url":"https://api.github.com/repos/falconry/falcon/releases{/id}","created_at":"2012-12-06T18:17:51Z","updated_at":"2015-03-24T23:09:41Z","pushed_at":"2015-03-25T14:28:36Z","git_url":"git://github.com/falconry/falcon.git","ssh_url":"git@github.com:falconry/falcon.git","clone_url":"https://github.com/falconry/falcon.git","svn_url":"https://github.com/falconry/falcon","homepage":"http://falconframework.org","size":13831,"stargazers_count":1537,"watchers_count":1537,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":170,"mirror_url":null,"open_issues_count":158,"forks":170,"open_issues":158,"watchers":1537,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/falconry/falcon/pulls/405"},"html":{"href":"https://github.com/falconry/falcon/pull/405"},"issue":{"href":"https://api.github.com/repos/falconry/falcon/issues/405"},"comments":{"href":"https://api.github.com/repos/falconry/falcon/issues/405/comments"},"review_comments":{"href":"https://api.github.com/repos/falconry/falcon/pulls/405/comments"},"review_comment":{"href":"https://api.github.com/repos/falconry/falcon/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/falconry/falcon/pulls/405/commits"},"statuses":{"href":"https://api.github.com/repos/falconry/falcon/statuses/a0a7870078f3f82c7918d5c62511aebdd83f8e3e"}}}}