Merge pull request #343 from channelcat/cookie-usability
Cookie deletion and default path
This commit is contained in:
commit
a4f85cd02e
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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']
|
||||||
|
|
Loading…
Reference in New Issue
Block a user