Merge pull request #343 from channelcat/cookie-usability

Cookie deletion and default path
This commit is contained in:
Channel Cat 2017-01-25 21:59:43 -08:00 committed by GitHub
commit a4f85cd02e
3 changed files with 58 additions and 4 deletions

View File

@ -32,12 +32,39 @@ async def test(request):
return response return response
``` ```
## Deleting cookies
Cookies can be removed semantically or explicitly.
```python
from sanic.response import text
@app.route("/cookie")
async def test(request):
response = text("Time to eat some cookies muahaha")
# This cookie will be set to expire in 0 seconds
del response.cookies['kill_me']
# This cookie will self destruct in 5 seconds
response.cookies['short_life'] = 'Glad to be here'
response.cookies['short_life']['max-age'] = 5
del response.cookies['favorite_color']
# This cookie will remain unchanged
response.cookies['favorite_color'] = 'blue'
response.cookies['favorite_color'] = 'pink'
del response.cookies['favorite_color']
return response
```
Response cookies can be set like dictionary values and have the following Response cookies can be set like dictionary values and have the following
parameters available: parameters available:
- `expires` (datetime): The time for the cookie to expire on the - `expires` (datetime): The time for the cookie to expire on the
client's browser. client's browser.
- `path` (string): The subset of URLs to which this cookie applies. - `path` (string): The subset of URLs to which this cookie applies. Defaults to /.
- `comment` (string): A comment (metadata). - `comment` (string): A comment (metadata).
- `domain` (string): Specifies the domain for which the cookie is valid. An - `domain` (string): Specifies the domain for which the cookie is valid. An
explicitly specified domain must always start with a dot. explicitly specified domain must always start with a dot.

View File

@ -42,8 +42,9 @@ class CookieJar(dict):
""" """
CookieJar dynamically writes headers as cookies are added and removed CookieJar dynamically writes headers as cookies are added and removed
It gets around the limitation of one header per name by using the It gets around the limitation of one header per name by using the
MultiHeader class to provide a unique key that encodes to Set-Cookie MultiHeader class to provide a unique key that encodes to Set-Cookie.
""" """
def __init__(self, headers): def __init__(self, headers):
super().__init__() super().__init__()
self.headers = headers self.headers = headers
@ -54,6 +55,7 @@ class CookieJar(dict):
cookie_header = self.cookie_headers.get(key) cookie_header = self.cookie_headers.get(key)
if not cookie_header: if not cookie_header:
cookie = Cookie(key, value) cookie = Cookie(key, value)
cookie['path'] = '/'
cookie_header = MultiHeader("Set-Cookie") cookie_header = MultiHeader("Set-Cookie")
self.cookie_headers[key] = cookie_header self.cookie_headers[key] = cookie_header
self.headers[cookie_header] = cookie self.headers[cookie_header] = cookie
@ -62,6 +64,12 @@ class CookieJar(dict):
self[key].value = value self[key].value = value
def __delitem__(self, key): def __delitem__(self, key):
if key not in self.cookie_headers:
self[key] = ''
self[key]['max-age'] = 0
else:
cookie_header = self.cookie_headers[key]
del self.headers[cookie_header]
del self.cookie_headers[key] del self.cookie_headers[key]
return super().__delitem__(key) return super().__delitem__(key)

View File

@ -76,3 +76,22 @@ def test_cookie_options():
assert response_cookies['test'].value == 'at you' assert response_cookies['test'].value == 'at you'
assert response_cookies['test']['httponly'] == True assert response_cookies['test']['httponly'] == True
def test_cookie_deletion():
app = Sanic('test_text')
@app.route('/')
def handler(request):
response = text("OK")
del response.cookies['i_want_to_die']
response.cookies['i_never_existed'] = 'testing'
del response.cookies['i_never_existed']
return response
request, response = sanic_endpoint_test(app)
response_cookies = SimpleCookie()
response_cookies.load(response.headers.get('Set-Cookie', {}))
assert int(response_cookies['i_want_to_die']['max-age']) == 0
with pytest.raises(KeyError):
hold_my_beer = response.cookies['i_never_existed']