0001-misc-let-django-generate-set-cookies-headers-72613.patch
tests/form_pages/test_all.py | ||
---|---|---|
5710 | 5710 |
create_formdef() |
5711 | 5711 |
app = get_app(pub) |
5712 | 5712 |
resp = app.get('/test/', status=200) |
5713 |
assert resp.headers['Set-Cookie'].startswith('sessionid-') |
|
5713 |
assert resp.headers['Set-Cookie'].strip().startswith('sessionid-')
|
|
5714 | 5714 |
assert 'HttpOnly' in resp.headers['Set-Cookie'] |
5715 | 5715 |
assert 'Secure' not in resp.headers['Set-Cookie'] |
5716 | 5716 | |
5717 | 5717 |
app = get_app(pub, https=True) |
5718 | 5718 |
resp = app.get('/test/', status=200) |
5719 |
assert resp.headers['Set-Cookie'].startswith('sessionid-') |
|
5719 |
assert resp.headers['Set-Cookie'].strip().startswith('sessionid-')
|
|
5720 | 5720 |
assert 'HttpOnly' in resp.headers['Set-Cookie'] |
5721 | 5721 |
assert 'Secure' in resp.headers['Set-Cookie'] |
5722 | 5722 |
tests/test_auth_pages.py | ||
---|---|---|
67 | 67 |
assert list(cookie_store.keys()) == [cookie_name] |
68 | 68 |
assert 'HttpOnly' in resp.headers['Set-Cookie'] |
69 | 69 |
assert 'SameSite=None' in resp.headers['Set-Cookie'] |
70 |
assert 'path=/' in resp.headers['Set-Cookie']
|
|
70 |
assert 'Path=/' in resp.headers['Set-Cookie']
|
|
71 | 71 | |
72 | 72 | |
73 | 73 |
def test_login_logout(pub): |
tests/test_saml_auth.py | ||
---|---|---|
607 | 607 |
assert 'Secure' in resp.headers['Set-Cookie'] |
608 | 608 |
assert 'HttpOnly' in resp.headers['Set-Cookie'] |
609 | 609 |
assert 'SameSite=None' in resp.headers['Set-Cookie'] |
610 |
assert 'path=/' in resp.headers['Set-Cookie']
|
|
610 |
assert 'Path=/' in resp.headers['Set-Cookie']
|
|
611 | 611 |
assert resp.status_int == 302 |
612 | 612 |
assert ( |
613 | 613 |
resp.location |
wcs/compat.py | ||
---|---|---|
33 | 33 |
from .qommon.publisher import set_publisher_class |
34 | 34 | |
35 | 35 | |
36 |
def transfer_cookies(quixote_response, django_response): |
|
37 |
for name, attrs in quixote_response.cookies.items(): |
|
38 |
value = str(attrs['value']) |
|
39 |
if 'samesite' not in attrs: |
|
40 |
attrs['samesite'] = 'None' |
|
41 |
kwargs = {} |
|
42 |
samesite_none = False |
|
43 |
for attr, val in attrs.items(): |
|
44 |
attr = attr.lower() |
|
45 |
if val is None: |
|
46 |
continue |
|
47 |
if attr == 'comment': |
|
48 |
continue |
|
49 |
if attr == 'samesite' and val.lower() == 'none': |
|
50 |
samesite_none = True |
|
51 |
elif attr in ('expires', 'domain', 'path', 'max_age', 'samesite'): |
|
52 |
kwargs[attr] = val |
|
53 |
elif attr in ('httponly', 'secure') and val: |
|
54 |
kwargs[attr] = True |
|
55 |
django_response.set_cookie(name, value, **kwargs) |
|
56 |
# work around absent support for None in django 2.2 |
|
57 |
if samesite_none: |
|
58 |
django_response.cookies[name]['samesite'] = 'None' |
|
59 | ||
60 | ||
36 | 61 |
class TemplateWithFallbackView(TemplateView): |
37 | 62 |
quixote_response = None |
38 | 63 | |
... | ... | |
70 | 95 |
else: |
71 | 96 |
response = self.render_to_response(context) |
72 | 97 | |
98 |
transfer_cookies(self.quixote_response, response) |
|
99 | ||
73 | 100 |
for name, value in self.quixote_response.generate_headers(): |
74 | 101 |
if name in ('Connection', 'Content-Length'): |
75 | 102 |
continue |
... | ... | |
83 | 110 |
if self.quixote_response and self.quixote_response.status_code != 200: |
84 | 111 |
django_response.status_code = self.quixote_response.status_code |
85 | 112 |
django_response.reason_phrase = self.quixote_response.reason_phrase |
113 |
transfer_cookies(self.quixote_response, django_response) |
|
86 | 114 |
for name, value in self.quixote_response.generate_headers(): |
87 | 115 |
if name in ('Connection', 'Content-Length'): |
88 | 116 |
continue |
... | ... | |
211 | 239 |
self.session_manager.finish_successful_request() |
212 | 240 |
request.ignore_session = True # no further changes |
213 | 241 | |
242 |
transfer_cookies(response, django_response) |
|
243 | ||
214 | 244 |
for name, value in response.generate_headers(): |
215 | 245 |
if name in ('Connection', 'Content-Length'): |
216 | 246 |
continue |
... | ... | |
264 | 294 |
reason=request.response.reason_phrase, |
265 | 295 |
) |
266 | 296 | |
297 |
transfer_cookies(request.response, django_response) |
|
298 | ||
267 | 299 |
for name, value in request.response.generate_headers(): |
268 | 300 |
if name in ('Connection', 'Content-Length'): |
269 | 301 |
continue |
wcs/middleware.py | ||
---|---|---|
26 | 26 |
from quixote import get_publisher |
27 | 27 |
from quixote.errors import RequestError |
28 | 28 | |
29 |
from .compat import CompatHTTPRequest, CompatWcsPublisher |
|
29 |
from .compat import CompatHTTPRequest, CompatWcsPublisher, transfer_cookies
|
|
30 | 30 |
from .qommon.http_response import HTTPResponse |
31 | 31 |
from .qommon.publisher import ImmediateRedirectException |
32 | 32 | |
... | ... | |
87 | 87 |
if compat_request.form: |
88 | 88 |
new_query_string = '?' + urllib.parse.urlencode(compat_request.form) |
89 | 89 |
response = HttpResponseRedirect(compat_request.get_path() + new_query_string) |
90 |
transfer_cookies(compat_request.response, response) |
|
90 | 91 |
for name, value in compat_request.response.generate_headers(): |
91 | 92 |
if name == 'Content-Length': |
92 | 93 |
continue |
wcs/qommon/http_response.py | ||
---|---|---|
35 | 35 |
self.charset = get_publisher().site_charset |
36 | 36 | |
37 | 37 |
def _gen_cookie_headers(self): |
38 |
cookie_headers = [] |
|
39 |
for name, attrs in self.cookies.items(): |
|
40 |
value = str(attrs['value']) |
|
41 |
if '"' in value: |
|
42 |
value = value.replace('"', '\\"') |
|
43 |
chunks = ['%s="%s"' % (name, value)] |
|
44 |
if 'samesite' not in attrs: |
|
45 |
attrs['samesite'] = 'None' |
|
46 |
for name, val in attrs.items(): |
|
47 |
name = name.lower() |
|
48 |
if val is None: |
|
49 |
continue |
|
50 |
if name in ('expires', 'domain', 'path', 'max_age', 'comment'): |
|
51 |
name = name.replace('_', '-') |
|
52 |
chunks.append('%s=%s' % (name, val)) |
|
53 |
elif name == 'samesite': |
|
54 |
chunks.append('SameSite=%s' % val) |
|
55 |
elif name == 'secure' and val: |
|
56 |
chunks.append('Secure') |
|
57 |
elif name == 'httponly' and val: |
|
58 |
chunks.append('HttpOnly') |
|
59 |
cookie_headers.append(('Set-Cookie', '; '.join(chunks))) |
|
60 |
return cookie_headers |
|
38 |
return [] |
|
61 | 39 | |
62 | 40 |
def reset_includes(self): |
63 | 41 |
self.javascript_scripts = None |
64 |
- |