diff options
Diffstat (limited to 'tests/test_http.py')
| -rw-r--r-- | tests/test_http.py | 784 |
1 files changed, 424 insertions, 360 deletions
diff --git a/tests/test_http.py b/tests/test_http.py index b261a605..c6e8309a 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -8,199 +8,222 @@ :copyright: 2007 Pallets :license: BSD-3-Clause """ -import pytest - from datetime import datetime -from tests import strict_eq -from werkzeug._compat import itervalues, wsgi_encoding_dance +import pytest -from werkzeug import http, datastructures +from . import strict_eq +from werkzeug import datastructures +from werkzeug import http +from werkzeug._compat import itervalues +from werkzeug._compat import wsgi_encoding_dance from werkzeug.test import create_environ class TestHTTPUtility(object): - def test_accept(self): - a = http.parse_accept_header('en-us,ru;q=0.5') - assert list(itervalues(a)) == ['en-us', 'ru'] - assert a.best == 'en-us' - assert a.find('ru') == 1 - pytest.raises(ValueError, a.index, 'de') - assert a.to_header() == 'en-us,ru;q=0.5' + a = http.parse_accept_header("en-us,ru;q=0.5") + assert list(itervalues(a)) == ["en-us", "ru"] + assert a.best == "en-us" + assert a.find("ru") == 1 + pytest.raises(ValueError, a.index, "de") + assert a.to_header() == "en-us,ru;q=0.5" def test_mime_accept(self): - a = http.parse_accept_header('text/xml,application/xml,' - 'application/xhtml+xml,' - 'application/foo;quiet=no; bar=baz;q=0.6,' - 'text/html;q=0.9,text/plain;q=0.8,' - 'image/png,*/*;q=0.5', - datastructures.MIMEAccept) - pytest.raises(ValueError, lambda: a['missing']) - assert a['image/png'] == 1 - assert a['text/plain'] == 0.8 - assert a['foo/bar'] == 0.5 - assert a['application/foo;quiet=no; bar=baz'] == 0.6 - assert a[a.find('foo/bar')] == ('*/*', 0.5) + a = http.parse_accept_header( + "text/xml,application/xml," + "application/xhtml+xml," + "application/foo;quiet=no; bar=baz;q=0.6," + "text/html;q=0.9,text/plain;q=0.8," + "image/png,*/*;q=0.5", + datastructures.MIMEAccept, + ) + pytest.raises(ValueError, lambda: a["missing"]) + assert a["image/png"] == 1 + assert a["text/plain"] == 0.8 + assert a["foo/bar"] == 0.5 + assert a["application/foo;quiet=no; bar=baz"] == 0.6 + assert a[a.find("foo/bar")] == ("*/*", 0.5) def test_accept_matches(self): - a = http.parse_accept_header('text/xml,application/xml,application/xhtml+xml,' - 'text/html;q=0.9,text/plain;q=0.8,' - 'image/png', datastructures.MIMEAccept) - assert a.best_match(['text/html', 'application/xhtml+xml']) == \ - 'application/xhtml+xml' - assert a.best_match(['text/html']) == 'text/html' - assert a.best_match(['foo/bar']) is None - assert a.best_match(['foo/bar', 'bar/foo'], default='foo/bar') == 'foo/bar' - assert a.best_match(['application/xml', 'text/xml']) == 'application/xml' + a = http.parse_accept_header( + "text/xml,application/xml,application/xhtml+xml," + "text/html;q=0.9,text/plain;q=0.8," + "image/png", + datastructures.MIMEAccept, + ) + assert ( + a.best_match(["text/html", "application/xhtml+xml"]) + == "application/xhtml+xml" + ) + assert a.best_match(["text/html"]) == "text/html" + assert a.best_match(["foo/bar"]) is None + assert a.best_match(["foo/bar", "bar/foo"], default="foo/bar") == "foo/bar" + assert a.best_match(["application/xml", "text/xml"]) == "application/xml" def test_charset_accept(self): - a = http.parse_accept_header('ISO-8859-1,utf-8;q=0.7,*;q=0.7', - datastructures.CharsetAccept) - assert a['iso-8859-1'] == a['iso8859-1'] - assert a['iso-8859-1'] == 1 - assert a['UTF8'] == 0.7 - assert a['ebcdic'] == 0.7 + a = http.parse_accept_header( + "ISO-8859-1,utf-8;q=0.7,*;q=0.7", datastructures.CharsetAccept + ) + assert a["iso-8859-1"] == a["iso8859-1"] + assert a["iso-8859-1"] == 1 + assert a["UTF8"] == 0.7 + assert a["ebcdic"] == 0.7 def test_language_accept(self): - a = http.parse_accept_header('de-AT,de;q=0.8,en;q=0.5', - datastructures.LanguageAccept) - assert a.best == 'de-AT' - assert 'de_AT' in a - assert 'en' in a - assert a['de-at'] == 1 - assert a['en'] == 0.5 + a = http.parse_accept_header( + "de-AT,de;q=0.8,en;q=0.5", datastructures.LanguageAccept + ) + assert a.best == "de-AT" + assert "de_AT" in a + assert "en" in a + assert a["de-at"] == 1 + assert a["en"] == 0.5 def test_set_header(self): hs = http.parse_set_header('foo, Bar, "Blah baz", Hehe') - assert 'blah baz' in hs - assert 'foobar' not in hs - assert 'foo' in hs - assert list(hs) == ['foo', 'Bar', 'Blah baz', 'Hehe'] - hs.add('Foo') + assert "blah baz" in hs + assert "foobar" not in hs + assert "foo" in hs + assert list(hs) == ["foo", "Bar", "Blah baz", "Hehe"] + hs.add("Foo") assert hs.to_header() == 'foo, Bar, "Blah baz", Hehe' def test_list_header(self): - hl = http.parse_list_header('foo baz, blah') - assert hl == ['foo baz', 'blah'] + hl = http.parse_list_header("foo baz, blah") + assert hl == ["foo baz", "blah"] def test_dict_header(self): d = http.parse_dict_header('foo="bar baz", blah=42') - assert d == {'foo': 'bar baz', 'blah': '42'} + assert d == {"foo": "bar baz", "blah": "42"} def test_cache_control_header(self): - cc = http.parse_cache_control_header('max-age=0, no-cache') + cc = http.parse_cache_control_header("max-age=0, no-cache") assert cc.max_age == 0 assert cc.no_cache - cc = http.parse_cache_control_header('private, community="UCI"', None, - datastructures.ResponseCacheControl) + cc = http.parse_cache_control_header( + 'private, community="UCI"', None, datastructures.ResponseCacheControl + ) assert cc.private - assert cc['community'] == 'UCI' + assert cc["community"] == "UCI" c = datastructures.ResponseCacheControl() assert c.no_cache is None assert c.private is None c.no_cache = True - assert c.no_cache == '*' + assert c.no_cache == "*" c.private = True - assert c.private == '*' + assert c.private == "*" del c.private assert c.private is None - assert c.to_header() == 'no-cache' + assert c.to_header() == "no-cache" def test_authorization_header(self): - a = http.parse_authorization_header('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==') - assert a.type == 'basic' - assert a.username == u'Aladdin' - assert a.password == u'open sesame' - - a = http.parse_authorization_header('Basic 0YDRg9GB0YHQutC40IE60JHRg9C60LLRiw==') - assert a.type == 'basic' - assert a.username == u'русскиЁ' - assert a.password == u'Буквы' - - a = http.parse_authorization_header('Basic 5pmu6YCa6K+dOuS4reaWhw==') - assert a.type == 'basic' - assert a.username == u'普通话' - assert a.password == u'中文' - - a = http.parse_authorization_header('''Digest username="Mufasa", - realm="testrealm@host.invalid", - nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", - uri="/dir/index.html", - qop=auth, - nc=00000001, - cnonce="0a4f113b", - response="6629fae49393a05397450978507c4ef1", - opaque="5ccc069c403ebaf9f0171e9517f40e41"''') - assert a.type == 'digest' - assert a.username == 'Mufasa' - assert a.realm == 'testrealm@host.invalid' - assert a.nonce == 'dcd98b7102dd2f0e8b11d0f600bfb0c093' - assert a.uri == '/dir/index.html' - assert a.qop == 'auth' - assert a.nc == '00000001' - assert a.cnonce == '0a4f113b' - assert a.response == '6629fae49393a05397450978507c4ef1' - assert a.opaque == '5ccc069c403ebaf9f0171e9517f40e41' - - a = http.parse_authorization_header('''Digest username="Mufasa", - realm="testrealm@host.invalid", - nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", - uri="/dir/index.html", - response="e257afa1414a3340d93d30955171dd0e", - opaque="5ccc069c403ebaf9f0171e9517f40e41"''') - assert a.type == 'digest' - assert a.username == 'Mufasa' - assert a.realm == 'testrealm@host.invalid' - assert a.nonce == 'dcd98b7102dd2f0e8b11d0f600bfb0c093' - assert a.uri == '/dir/index.html' - assert a.response == 'e257afa1414a3340d93d30955171dd0e' - assert a.opaque == '5ccc069c403ebaf9f0171e9517f40e41' - - assert http.parse_authorization_header('') is None + a = http.parse_authorization_header("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==") + assert a.type == "basic" + assert a.username == u"Aladdin" + assert a.password == u"open sesame" + + a = http.parse_authorization_header( + "Basic 0YDRg9GB0YHQutC40IE60JHRg9C60LLRiw==" + ) + assert a.type == "basic" + assert a.username == u"русскиЁ" + assert a.password == u"Буквы" + + a = http.parse_authorization_header("Basic 5pmu6YCa6K+dOuS4reaWhw==") + assert a.type == "basic" + assert a.username == u"普通话" + assert a.password == u"中文" + + a = http.parse_authorization_header( + '''Digest username="Mufasa", + realm="testrealm@host.invalid", + nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", + uri="/dir/index.html", + qop=auth, + nc=00000001, + cnonce="0a4f113b", + response="6629fae49393a05397450978507c4ef1", + opaque="5ccc069c403ebaf9f0171e9517f40e41"''' + ) + assert a.type == "digest" + assert a.username == "Mufasa" + assert a.realm == "testrealm@host.invalid" + assert a.nonce == "dcd98b7102dd2f0e8b11d0f600bfb0c093" + assert a.uri == "/dir/index.html" + assert a.qop == "auth" + assert a.nc == "00000001" + assert a.cnonce == "0a4f113b" + assert a.response == "6629fae49393a05397450978507c4ef1" + assert a.opaque == "5ccc069c403ebaf9f0171e9517f40e41" + + a = http.parse_authorization_header( + '''Digest username="Mufasa", + realm="testrealm@host.invalid", + nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", + uri="/dir/index.html", + response="e257afa1414a3340d93d30955171dd0e", + opaque="5ccc069c403ebaf9f0171e9517f40e41"''' + ) + assert a.type == "digest" + assert a.username == "Mufasa" + assert a.realm == "testrealm@host.invalid" + assert a.nonce == "dcd98b7102dd2f0e8b11d0f600bfb0c093" + assert a.uri == "/dir/index.html" + assert a.response == "e257afa1414a3340d93d30955171dd0e" + assert a.opaque == "5ccc069c403ebaf9f0171e9517f40e41" + + assert http.parse_authorization_header("") is None assert http.parse_authorization_header(None) is None - assert http.parse_authorization_header('foo') is None + assert http.parse_authorization_header("foo") is None def test_www_authenticate_header(self): wa = http.parse_www_authenticate_header('Basic realm="WallyWorld"') - assert wa.type == 'basic' - assert wa.realm == 'WallyWorld' - wa.realm = 'Foo Bar' + assert wa.type == "basic" + assert wa.realm == "WallyWorld" + wa.realm = "Foo Bar" assert wa.to_header() == 'Basic realm="Foo Bar"' - wa = http.parse_www_authenticate_header('''Digest - realm="testrealm@host.com", - qop="auth,auth-int", - nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", - opaque="5ccc069c403ebaf9f0171e9517f40e41"''') - assert wa.type == 'digest' - assert wa.realm == 'testrealm@host.com' - assert 'auth' in wa.qop - assert 'auth-int' in wa.qop - assert wa.nonce == 'dcd98b7102dd2f0e8b11d0f600bfb0c093' - assert wa.opaque == '5ccc069c403ebaf9f0171e9517f40e41' + wa = http.parse_www_authenticate_header( + '''Digest + realm="testrealm@host.com", + qop="auth,auth-int", + nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", + opaque="5ccc069c403ebaf9f0171e9517f40e41"''' + ) + assert wa.type == "digest" + assert wa.realm == "testrealm@host.com" + assert "auth" in wa.qop + assert "auth-int" in wa.qop + assert wa.nonce == "dcd98b7102dd2f0e8b11d0f600bfb0c093" + assert wa.opaque == "5ccc069c403ebaf9f0171e9517f40e41" - wa = http.parse_www_authenticate_header('broken') - assert wa.type == 'broken' + wa = http.parse_www_authenticate_header("broken") + assert wa.type == "broken" - assert not http.parse_www_authenticate_header('').type - assert not http.parse_www_authenticate_header('') + assert not http.parse_www_authenticate_header("").type + assert not http.parse_www_authenticate_header("") def test_etags(self): - assert http.quote_etag('foo') == '"foo"' - assert http.quote_etag('foo', True) == 'W/"foo"' - assert http.unquote_etag('"foo"') == ('foo', False) - assert http.unquote_etag('W/"foo"') == ('foo', True) + assert http.quote_etag("foo") == '"foo"' + assert http.quote_etag("foo", True) == 'W/"foo"' + assert http.unquote_etag('"foo"') == ("foo", False) + assert http.unquote_etag('W/"foo"') == ("foo", True) es = http.parse_etags('"foo", "bar", W/"baz", blar') - assert sorted(es) == ['bar', 'blar', 'foo'] - assert 'foo' in es - assert 'baz' not in es - assert es.contains_weak('baz') - assert 'blar' in es + assert sorted(es) == ["bar", "blar", "foo"] + assert "foo" in es + assert "baz" not in es + assert es.contains_weak("baz") + assert "blar" in es assert es.contains_raw('W/"baz"') assert es.contains_raw('"foo"') - assert sorted(es.to_header().split(', ')) == ['"bar"', '"blar"', '"foo"', 'W/"baz"'] + assert sorted(es.to_header().split(", ")) == [ + '"bar"', + '"blar"', + '"foo"', + 'W/"baz"', + ] def test_etags_nonzero(self): etags = http.parse_etags('W/"foo"') @@ -208,392 +231,433 @@ class TestHTTPUtility(object): assert etags.contains_raw('W/"foo"') def test_parse_date(self): - assert http.parse_date('Sun, 06 Nov 1994 08:49:37 GMT ') == datetime( - 1994, 11, 6, 8, 49, 37) - assert http.parse_date('Sunday, 06-Nov-94 08:49:37 GMT') == datetime(1994, 11, 6, 8, 49, 37) - assert http.parse_date(' Sun Nov 6 08:49:37 1994') == datetime(1994, 11, 6, 8, 49, 37) - assert http.parse_date('foo') is None + assert http.parse_date("Sun, 06 Nov 1994 08:49:37 GMT ") == datetime( + 1994, 11, 6, 8, 49, 37 + ) + assert http.parse_date("Sunday, 06-Nov-94 08:49:37 GMT") == datetime( + 1994, 11, 6, 8, 49, 37 + ) + assert http.parse_date(" Sun Nov 6 08:49:37 1994") == datetime( + 1994, 11, 6, 8, 49, 37 + ) + assert http.parse_date("foo") is None def test_parse_date_overflows(self): - assert http.parse_date(' Sun 02 Feb 1343 08:49:37 GMT') == datetime(1343, 2, 2, 8, 49, 37) - assert http.parse_date('Thu, 01 Jan 1970 00:00:00 GMT') == datetime(1970, 1, 1, 0, 0) - assert http.parse_date('Thu, 33 Jan 1970 00:00:00 GMT') is None + assert http.parse_date(" Sun 02 Feb 1343 08:49:37 GMT") == datetime( + 1343, 2, 2, 8, 49, 37 + ) + assert http.parse_date("Thu, 01 Jan 1970 00:00:00 GMT") == datetime( + 1970, 1, 1, 0, 0 + ) + assert http.parse_date("Thu, 33 Jan 1970 00:00:00 GMT") is None def test_remove_entity_headers(self): now = http.http_date() - headers1 = [('Date', now), ('Content-Type', 'text/html'), ('Content-Length', '0')] + headers1 = [ + ("Date", now), + ("Content-Type", "text/html"), + ("Content-Length", "0"), + ] headers2 = datastructures.Headers(headers1) http.remove_entity_headers(headers1) - assert headers1 == [('Date', now)] + assert headers1 == [("Date", now)] http.remove_entity_headers(headers2) - assert headers2 == datastructures.Headers([(u'Date', now)]) + assert headers2 == datastructures.Headers([(u"Date", now)]) def test_remove_hop_by_hop_headers(self): - headers1 = [('Connection', 'closed'), ('Foo', 'bar'), - ('Keep-Alive', 'wtf')] + headers1 = [("Connection", "closed"), ("Foo", "bar"), ("Keep-Alive", "wtf")] headers2 = datastructures.Headers(headers1) http.remove_hop_by_hop_headers(headers1) - assert headers1 == [('Foo', 'bar')] + assert headers1 == [("Foo", "bar")] http.remove_hop_by_hop_headers(headers2) - assert headers2 == datastructures.Headers([('Foo', 'bar')]) + assert headers2 == datastructures.Headers([("Foo", "bar")]) def test_parse_options_header(self): - assert http.parse_options_header(None) == \ - ('', {}) - assert http.parse_options_header("") == \ - ('', {}) - assert http.parse_options_header(r'something; foo="other\"thing"') == \ - ('something', {'foo': 'other"thing'}) - assert http.parse_options_header(r'something; foo="other\"thing"; meh=42') == \ - ('something', {'foo': 'other"thing', 'meh': '42'}) - assert http.parse_options_header(r'something; foo="other\"thing"; meh=42; bleh') == \ - ('something', {'foo': 'other"thing', 'meh': '42', 'bleh': None}) - assert http.parse_options_header('something; foo="other;thing"; meh=42; bleh') == \ - ('something', {'foo': 'other;thing', 'meh': '42', 'bleh': None}) - assert http.parse_options_header('something; foo="otherthing"; meh=; bleh') == \ - ('something', {'foo': 'otherthing', 'meh': None, 'bleh': None}) + assert http.parse_options_header(None) == ("", {}) + assert http.parse_options_header("") == ("", {}) + assert http.parse_options_header(r'something; foo="other\"thing"') == ( + "something", + {"foo": 'other"thing'}, + ) + assert http.parse_options_header(r'something; foo="other\"thing"; meh=42') == ( + "something", + {"foo": 'other"thing', "meh": "42"}, + ) + assert http.parse_options_header( + r'something; foo="other\"thing"; meh=42; bleh' + ) == ("something", {"foo": 'other"thing', "meh": "42", "bleh": None}) + assert http.parse_options_header( + 'something; foo="other;thing"; meh=42; bleh' + ) == ("something", {"foo": "other;thing", "meh": "42", "bleh": None}) + assert http.parse_options_header('something; foo="otherthing"; meh=; bleh') == ( + "something", + {"foo": "otherthing", "meh": None, "bleh": None}, + ) # Issue #404 - assert http.parse_options_header('multipart/form-data; name="foo bar"; ' - 'filename="bar foo"') == \ - ('multipart/form-data', {'name': 'foo bar', 'filename': 'bar foo'}) + assert http.parse_options_header( + 'multipart/form-data; name="foo bar"; ' 'filename="bar foo"' + ) == ("multipart/form-data", {"name": "foo bar", "filename": "bar foo"}) # Examples from RFC - assert http.parse_options_header('audio/*; q=0.2, audio/basic') == \ - ('audio/*', {'q': '0.2'}) - assert http.parse_options_header('audio/*; q=0.2, audio/basic', multiple=True) == \ - ('audio/*', {'q': '0.2'}, "audio/basic", {}) + assert http.parse_options_header("audio/*; q=0.2, audio/basic") == ( + "audio/*", + {"q": "0.2"}, + ) + assert http.parse_options_header( + "audio/*; q=0.2, audio/basic", multiple=True + ) == ("audio/*", {"q": "0.2"}, "audio/basic", {}) + assert http.parse_options_header( + "text/plain; q=0.5, text/html\n text/x-dvi; q=0.8, text/x-c", + multiple=True, + ) == ( + "text/plain", + {"q": "0.5"}, + "text/html", + {}, + "text/x-dvi", + {"q": "0.8"}, + "text/x-c", + {}, + ) assert http.parse_options_header( - 'text/plain; q=0.5, text/html\n ' - 'text/x-dvi; q=0.8, text/x-c', - multiple=True) == \ - ('text/plain', {'q': '0.5'}, "text/html", {}, - "text/x-dvi", {'q': '0.8'}, "text/x-c", {}) - assert http.parse_options_header('text/plain; q=0.5, text/html\n' - ' ' - 'text/x-dvi; q=0.8, text/x-c') == \ - ('text/plain', {'q': '0.5'}) + "text/plain; q=0.5, text/html\n text/x-dvi; q=0.8, text/x-c" + ) == ("text/plain", {"q": "0.5"}) # Issue #932 assert http.parse_options_header( - 'form-data; ' - 'name="a_file"; ' - 'filename*=UTF-8\'\'' - '"%c2%a3%20and%20%e2%82%ac%20rates"') == \ - ('form-data', {'name': 'a_file', - 'filename': u'\xa3 and \u20ac rates'}) + "form-data; name=\"a_file\"; filename*=UTF-8''" + '"%c2%a3%20and%20%e2%82%ac%20rates"' + ) == ("form-data", {"name": "a_file", "filename": u"\xa3 and \u20ac rates"}) assert http.parse_options_header( - 'form-data; ' - 'name*=UTF-8\'\'"%C5%AAn%C4%ADc%C5%8Dde%CC%BD"; ' - 'filename="some_file.txt"') == \ - ('form-data', {'name': u'\u016an\u012dc\u014dde\u033d', - 'filename': 'some_file.txt'}) + "form-data; name*=UTF-8''\"%C5%AAn%C4%ADc%C5%8Dde%CC%BD\"; " + 'filename="some_file.txt"' + ) == ( + "form-data", + {"name": u"\u016an\u012dc\u014dde\u033d", "filename": "some_file.txt"}, + ) def test_parse_options_header_value_with_quotes(self): assert http.parse_options_header( 'form-data; name="file"; filename="t\'es\'t.txt"' - ) == ('form-data', {'name': 'file', 'filename': "t'es't.txt"}) + ) == ("form-data", {"name": "file", "filename": "t'es't.txt"}) assert http.parse_options_header( - 'form-data; name="file"; filename*=UTF-8\'\'"\'🐍\'.txt"' - ) == ('form-data', {'name': 'file', 'filename': u"'🐍'.txt"}) + "form-data; name=\"file\"; filename*=UTF-8''\"'🐍'.txt\"" + ) == ("form-data", {"name": "file", "filename": u"'🐍'.txt"}) def test_parse_options_header_broken_values(self): # Issue #995 - assert http.parse_options_header(' ') == ('', {}) - assert http.parse_options_header(' , ') == ('', {}) - assert http.parse_options_header(' ; ') == ('', {}) - assert http.parse_options_header(' ,; ') == ('', {}) - assert http.parse_options_header(' , a ') == ('', {}) - assert http.parse_options_header(' ; a ') == ('', {}) + assert http.parse_options_header(" ") == ("", {}) + assert http.parse_options_header(" , ") == ("", {}) + assert http.parse_options_header(" ; ") == ("", {}) + assert http.parse_options_header(" ,; ") == ("", {}) + assert http.parse_options_header(" , a ") == ("", {}) + assert http.parse_options_header(" ; a ") == ("", {}) def test_dump_options_header(self): - assert http.dump_options_header('foo', {'bar': 42}) == \ - 'foo; bar=42' - assert http.dump_options_header('foo', {'bar': 42, 'fizz': None}) in \ - ('foo; bar=42; fizz', 'foo; fizz; bar=42') + assert http.dump_options_header("foo", {"bar": 42}) == "foo; bar=42" + assert http.dump_options_header("foo", {"bar": 42, "fizz": None}) in ( + "foo; bar=42; fizz", + "foo; fizz; bar=42", + ) def test_dump_header(self): - assert http.dump_header([1, 2, 3]) == '1, 2, 3' + assert http.dump_header([1, 2, 3]) == "1, 2, 3" assert http.dump_header([1, 2, 3], allow_token=False) == '"1", "2", "3"' - assert http.dump_header({'foo': 'bar'}, allow_token=False) == 'foo="bar"' - assert http.dump_header({'foo': 'bar'}) == 'foo=bar' + assert http.dump_header({"foo": "bar"}, allow_token=False) == 'foo="bar"' + assert http.dump_header({"foo": "bar"}) == "foo=bar" def test_is_resource_modified(self): env = create_environ() # ignore POST - env['REQUEST_METHOD'] = 'POST' - assert not http.is_resource_modified(env, etag='testing') - env['REQUEST_METHOD'] = 'GET' + env["REQUEST_METHOD"] = "POST" + assert not http.is_resource_modified(env, etag="testing") + env["REQUEST_METHOD"] = "GET" # etagify from data - pytest.raises(TypeError, http.is_resource_modified, env, - data='42', etag='23') - env['HTTP_IF_NONE_MATCH'] = http.generate_etag(b'awesome') - assert not http.is_resource_modified(env, data=b'awesome') + pytest.raises(TypeError, http.is_resource_modified, env, data="42", etag="23") + env["HTTP_IF_NONE_MATCH"] = http.generate_etag(b"awesome") + assert not http.is_resource_modified(env, data=b"awesome") - env['HTTP_IF_MODIFIED_SINCE'] = http.http_date(datetime(2008, 1, 1, 12, 30)) - assert not http.is_resource_modified(env, - last_modified=datetime(2008, 1, 1, 12, 00)) - assert http.is_resource_modified(env, - last_modified=datetime(2008, 1, 1, 13, 00)) + env["HTTP_IF_MODIFIED_SINCE"] = http.http_date(datetime(2008, 1, 1, 12, 30)) + assert not http.is_resource_modified( + env, last_modified=datetime(2008, 1, 1, 12, 00) + ) + assert http.is_resource_modified( + env, last_modified=datetime(2008, 1, 1, 13, 00) + ) def test_is_resource_modified_for_range_requests(self): env = create_environ() - env['HTTP_IF_MODIFIED_SINCE'] = http.http_date(datetime(2008, 1, 1, 12, 30)) - env['HTTP_IF_RANGE'] = http.generate_etag(b'awesome_if_range') + env["HTTP_IF_MODIFIED_SINCE"] = http.http_date(datetime(2008, 1, 1, 12, 30)) + env["HTTP_IF_RANGE"] = http.generate_etag(b"awesome_if_range") # Range header not present, so If-Range should be ignored - assert not http.is_resource_modified(env, data=b'not_the_same', - ignore_if_range=False, - last_modified=datetime(2008, 1, 1, 12, 30)) - - env['HTTP_RANGE'] = '' - assert not http.is_resource_modified(env, data=b'awesome_if_range', - ignore_if_range=False) - assert http.is_resource_modified(env, data=b'not_the_same', - ignore_if_range=False) - - env['HTTP_IF_RANGE'] = http.http_date(datetime(2008, 1, 1, 13, 30)) - assert http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 14, 00), - ignore_if_range=False) - assert not http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 13, 30), - ignore_if_range=False) - assert http.is_resource_modified(env, last_modified=datetime(2008, 1, 1, 13, 30), - ignore_if_range=True) + assert not http.is_resource_modified( + env, + data=b"not_the_same", + ignore_if_range=False, + last_modified=datetime(2008, 1, 1, 12, 30), + ) + + env["HTTP_RANGE"] = "" + assert not http.is_resource_modified( + env, data=b"awesome_if_range", ignore_if_range=False + ) + assert http.is_resource_modified( + env, data=b"not_the_same", ignore_if_range=False + ) + + env["HTTP_IF_RANGE"] = http.http_date(datetime(2008, 1, 1, 13, 30)) + assert http.is_resource_modified( + env, last_modified=datetime(2008, 1, 1, 14, 00), ignore_if_range=False + ) + assert not http.is_resource_modified( + env, last_modified=datetime(2008, 1, 1, 13, 30), ignore_if_range=False + ) + assert http.is_resource_modified( + env, last_modified=datetime(2008, 1, 1, 13, 30), ignore_if_range=True + ) def test_date_formatting(self): - assert http.cookie_date(0) == 'Thu, 01-Jan-1970 00:00:00 GMT' - assert http.cookie_date(datetime(1970, 1, 1)) == 'Thu, 01-Jan-1970 00:00:00 GMT' - assert http.http_date(0) == 'Thu, 01 Jan 1970 00:00:00 GMT' - assert http.http_date(datetime(1970, 1, 1)) == 'Thu, 01 Jan 1970 00:00:00 GMT' + assert http.cookie_date(0) == "Thu, 01-Jan-1970 00:00:00 GMT" + assert http.cookie_date(datetime(1970, 1, 1)) == "Thu, 01-Jan-1970 00:00:00 GMT" + assert http.http_date(0) == "Thu, 01 Jan 1970 00:00:00 GMT" + assert http.http_date(datetime(1970, 1, 1)) == "Thu, 01 Jan 1970 00:00:00 GMT" def test_cookies(self): strict_eq( - dict(http.parse_cookie('dismiss-top=6; CP=null*; PHPSESSID=0a539d42abc001cd' - 'c762809248d4beed; a=42; b="\\\";"')), + dict( + http.parse_cookie( + "dismiss-top=6; CP=null*; PHPSESSID=0a539d42abc001cd" + 'c762809248d4beed; a=42; b="\\";"' + ) + ), { - 'CP': u'null*', - 'PHPSESSID': u'0a539d42abc001cdc762809248d4beed', - 'a': u'42', - 'dismiss-top': u'6', - 'b': u'\";' - } - ) - rv = http.dump_cookie('foo', 'bar baz blub', 360, httponly=True, - sync_expires=False) + "CP": u"null*", + "PHPSESSID": u"0a539d42abc001cdc762809248d4beed", + "a": u"42", + "dismiss-top": u"6", + "b": u'";', + }, + ) + rv = http.dump_cookie( + "foo", "bar baz blub", 360, httponly=True, sync_expires=False + ) assert type(rv) is str - assert set(rv.split('; ')) == set(['HttpOnly', 'Max-Age=360', - 'Path=/', 'foo="bar baz blub"']) + assert set(rv.split("; ")) == { + "HttpOnly", + "Max-Age=360", + "Path=/", + 'foo="bar baz blub"', + } - strict_eq(dict(http.parse_cookie('fo234{=bar; blub=Blah')), - {'fo234{': u'bar', 'blub': u'Blah'}) + strict_eq( + dict(http.parse_cookie("fo234{=bar; blub=Blah")), + {"fo234{": u"bar", "blub": u"Blah"}, + ) - strict_eq(http.dump_cookie('key', 'xxx/'), 'key=xxx/; Path=/') - strict_eq(http.dump_cookie('key', 'xxx='), 'key=xxx=; Path=/') + strict_eq(http.dump_cookie("key", "xxx/"), "key=xxx/; Path=/") + strict_eq(http.dump_cookie("key", "xxx="), "key=xxx=; Path=/") def test_bad_cookies(self): strict_eq( - dict(http.parse_cookie( - 'first=IamTheFirst ; a=1; oops ; a=2 ;second = andMeTwo;' - )), - { - 'first': u'IamTheFirst', - 'a': u'2', - 'oops': u'', - 'second': u'andMeTwo', - } + dict( + http.parse_cookie( + "first=IamTheFirst ; a=1; oops ; a=2 ;second = andMeTwo;" + ) + ), + {"first": u"IamTheFirst", "a": u"2", "oops": u"", "second": u"andMeTwo"}, ) def test_empty_keys_are_ignored(self): strict_eq( - dict(http.parse_cookie( - 'first=IamTheFirst ; a=1; a=2 ;second=andMeTwo; ; ' - )), - { - 'first': u'IamTheFirst', - 'a': u'2', - 'second': u'andMeTwo' - } + dict( + http.parse_cookie("first=IamTheFirst ; a=1; a=2 ;second=andMeTwo; ; ") + ), + {"first": u"IamTheFirst", "a": u"2", "second": u"andMeTwo"}, ) def test_cookie_quoting(self): val = http.dump_cookie("foo", "?foo") strict_eq(val, 'foo="?foo"; Path=/') - strict_eq(dict(http.parse_cookie(val)), {'foo': u'?foo'}) + strict_eq(dict(http.parse_cookie(val)), {"foo": u"?foo"}) - strict_eq(dict(http.parse_cookie(r'foo="foo\054bar"')), - {'foo': u'foo,bar'}) + strict_eq(dict(http.parse_cookie(r'foo="foo\054bar"')), {"foo": u"foo,bar"}) def test_cookie_domain_resolving(self): - val = http.dump_cookie('foo', 'bar', domain=u'\N{SNOWMAN}.com') - strict_eq(val, 'foo=bar; Domain=xn--n3h.com; Path=/') + val = http.dump_cookie("foo", "bar", domain=u"\N{SNOWMAN}.com") + strict_eq(val, "foo=bar; Domain=xn--n3h.com; Path=/") def test_cookie_unicode_dumping(self): - val = http.dump_cookie('foo', u'\N{SNOWMAN}') + val = http.dump_cookie("foo", u"\N{SNOWMAN}") h = datastructures.Headers() - h.add('Set-Cookie', val) - assert h['Set-Cookie'] == 'foo="\\342\\230\\203"; Path=/' + h.add("Set-Cookie", val) + assert h["Set-Cookie"] == 'foo="\\342\\230\\203"; Path=/' - cookies = http.parse_cookie(h['Set-Cookie']) - assert cookies['foo'] == u'\N{SNOWMAN}' + cookies = http.parse_cookie(h["Set-Cookie"]) + assert cookies["foo"] == u"\N{SNOWMAN}" def test_cookie_unicode_keys(self): # Yes, this is technically against the spec but happens - val = http.dump_cookie(u'fö', u'fö') - assert val == wsgi_encoding_dance(u'fö="f\\303\\266"; Path=/', 'utf-8') + val = http.dump_cookie(u"fö", u"fö") + assert val == wsgi_encoding_dance(u'fö="f\\303\\266"; Path=/', "utf-8") cookies = http.parse_cookie(val) - assert cookies[u'fö'] == u'fö' + assert cookies[u"fö"] == u"fö" def test_cookie_unicode_parsing(self): # This is actually a correct test. This is what is being submitted # by firefox if you set an unicode cookie and we get the cookie sent # in on Python 3 under PEP 3333. - cookies = http.parse_cookie(u'fö=fö') - assert cookies[u'fö'] == u'fö' + cookies = http.parse_cookie(u"fö=fö") + assert cookies[u"fö"] == u"fö" def test_cookie_domain_encoding(self): - val = http.dump_cookie('foo', 'bar', domain=u'\N{SNOWMAN}.com') - strict_eq(val, 'foo=bar; Domain=xn--n3h.com; Path=/') + val = http.dump_cookie("foo", "bar", domain=u"\N{SNOWMAN}.com") + strict_eq(val, "foo=bar; Domain=xn--n3h.com; Path=/") - val = http.dump_cookie('foo', 'bar', domain=u'.\N{SNOWMAN}.com') - strict_eq(val, 'foo=bar; Domain=.xn--n3h.com; Path=/') + val = http.dump_cookie("foo", "bar", domain=u".\N{SNOWMAN}.com") + strict_eq(val, "foo=bar; Domain=.xn--n3h.com; Path=/") - val = http.dump_cookie('foo', 'bar', domain=u'.foo.com') - strict_eq(val, 'foo=bar; Domain=.foo.com; Path=/') + val = http.dump_cookie("foo", "bar", domain=u".foo.com") + strict_eq(val, "foo=bar; Domain=.foo.com; Path=/") def test_cookie_maxsize(self, recwarn): - val = http.dump_cookie('foo', 'bar' * 1360 + 'b') + val = http.dump_cookie("foo", "bar" * 1360 + "b") assert len(recwarn) == 0 assert len(val) == 4093 - http.dump_cookie('foo', 'bar' * 1360 + 'ba') + http.dump_cookie("foo", "bar" * 1360 + "ba") assert len(recwarn) == 1 w = recwarn.pop() - assert 'cookie is too large' in str(w.message) + assert "cookie is too large" in str(w.message) - http.dump_cookie('foo', b'w' * 502, max_size=512) + http.dump_cookie("foo", b"w" * 502, max_size=512) assert len(recwarn) == 1 w = recwarn.pop() - assert 'the limit is 512 bytes' in str(w.message) - - @pytest.mark.parametrize('input, expected', [ - ('strict', 'foo=bar; Path=/; SameSite=Strict'), - ('lax', 'foo=bar; Path=/; SameSite=Lax'), - (None, 'foo=bar; Path=/'), - ]) + assert "the limit is 512 bytes" in str(w.message) + + @pytest.mark.parametrize( + "input, expected", + [ + ("strict", "foo=bar; Path=/; SameSite=Strict"), + ("lax", "foo=bar; Path=/; SameSite=Lax"), + (None, "foo=bar; Path=/"), + ], + ) def test_cookie_samesite_attribute(self, input, expected): - val = http.dump_cookie('foo', 'bar', samesite=input) + val = http.dump_cookie("foo", "bar", samesite=input) strict_eq(val, expected) class TestRange(object): - def test_if_range_parsing(self): rv = http.parse_if_range_header('"Test"') - assert rv.etag == 'Test' + assert rv.etag == "Test" assert rv.date is None assert rv.to_header() == '"Test"' # weak information is dropped rv = http.parse_if_range_header('W/"Test"') - assert rv.etag == 'Test' + assert rv.etag == "Test" assert rv.date is None assert rv.to_header() == '"Test"' # broken etags are supported too - rv = http.parse_if_range_header('bullshit') - assert rv.etag == 'bullshit' + rv = http.parse_if_range_header("bullshit") + assert rv.etag == "bullshit" assert rv.date is None assert rv.to_header() == '"bullshit"' - rv = http.parse_if_range_header('Thu, 01 Jan 1970 00:00:00 GMT') + rv = http.parse_if_range_header("Thu, 01 Jan 1970 00:00:00 GMT") assert rv.etag is None assert rv.date == datetime(1970, 1, 1) - assert rv.to_header() == 'Thu, 01 Jan 1970 00:00:00 GMT' + assert rv.to_header() == "Thu, 01 Jan 1970 00:00:00 GMT" - for x in '', None: + for x in "", None: rv = http.parse_if_range_header(x) assert rv.etag is None assert rv.date is None - assert rv.to_header() == '' + assert rv.to_header() == "" def test_range_parsing(self): - rv = http.parse_range_header('bytes=52') + rv = http.parse_range_header("bytes=52") assert rv is None - rv = http.parse_range_header('bytes=52-') - assert rv.units == 'bytes' + rv = http.parse_range_header("bytes=52-") + assert rv.units == "bytes" assert rv.ranges == [(52, None)] - assert rv.to_header() == 'bytes=52-' + assert rv.to_header() == "bytes=52-" - rv = http.parse_range_header('bytes=52-99') - assert rv.units == 'bytes' + rv = http.parse_range_header("bytes=52-99") + assert rv.units == "bytes" assert rv.ranges == [(52, 100)] - assert rv.to_header() == 'bytes=52-99' + assert rv.to_header() == "bytes=52-99" - rv = http.parse_range_header('bytes=52-99,-1000') - assert rv.units == 'bytes' + rv = http.parse_range_header("bytes=52-99,-1000") + assert rv.units == "bytes" assert rv.ranges == [(52, 100), (-1000, None)] - assert rv.to_header() == 'bytes=52-99,-1000' + assert rv.to_header() == "bytes=52-99,-1000" - rv = http.parse_range_header('bytes = 1 - 100') - assert rv.units == 'bytes' + rv = http.parse_range_header("bytes = 1 - 100") + assert rv.units == "bytes" assert rv.ranges == [(1, 101)] - assert rv.to_header() == 'bytes=1-100' + assert rv.to_header() == "bytes=1-100" - rv = http.parse_range_header('AWesomes=0-999') - assert rv.units == 'awesomes' + rv = http.parse_range_header("AWesomes=0-999") + assert rv.units == "awesomes" assert rv.ranges == [(0, 1000)] - assert rv.to_header() == 'awesomes=0-999' + assert rv.to_header() == "awesomes=0-999" - rv = http.parse_range_header('bytes=-') + rv = http.parse_range_header("bytes=-") assert rv is None - rv = http.parse_range_header('bytes=bad') + rv = http.parse_range_header("bytes=bad") assert rv is None - rv = http.parse_range_header('bytes=bad-1') + rv = http.parse_range_header("bytes=bad-1") assert rv is None - rv = http.parse_range_header('bytes=-bad') + rv = http.parse_range_header("bytes=-bad") assert rv is None - rv = http.parse_range_header('bytes=52-99, bad') + rv = http.parse_range_header("bytes=52-99, bad") assert rv is None def test_content_range_parsing(self): - rv = http.parse_content_range_header('bytes 0-98/*') - assert rv.units == 'bytes' + rv = http.parse_content_range_header("bytes 0-98/*") + assert rv.units == "bytes" assert rv.start == 0 assert rv.stop == 99 assert rv.length is None - assert rv.to_header() == 'bytes 0-98/*' + assert rv.to_header() == "bytes 0-98/*" - rv = http.parse_content_range_header('bytes 0-98/*asdfsa') + rv = http.parse_content_range_header("bytes 0-98/*asdfsa") assert rv is None - rv = http.parse_content_range_header('bytes 0-99/100') - assert rv.to_header() == 'bytes 0-99/100' + rv = http.parse_content_range_header("bytes 0-99/100") + assert rv.to_header() == "bytes 0-99/100" rv.start = None rv.stop = None - assert rv.units == 'bytes' - assert rv.to_header() == 'bytes */100' + assert rv.units == "bytes" + assert rv.to_header() == "bytes */100" - rv = http.parse_content_range_header('bytes */100') + rv = http.parse_content_range_header("bytes */100") assert rv.start is None assert rv.stop is None assert rv.length == 100 - assert rv.units == 'bytes' + assert rv.units == "bytes" class TestRegression(object): - def test_best_match_works(self): # was a bug in 0.6 - rv = http.parse_accept_header('foo=,application/xml,application/xhtml+xml,' - 'text/html;q=0.9,text/plain;q=0.8,' - 'image/png,*/*;q=0.5', - datastructures.MIMEAccept).best_match(['foo/bar']) - assert rv == 'foo/bar' + rv = http.parse_accept_header( + "foo=,application/xml,application/xhtml+xml," + "text/html;q=0.9,text/plain;q=0.8," + "image/png,*/*;q=0.5", + datastructures.MIMEAccept, + ).best_match(["foo/bar"]) + assert rv == "foo/bar" |
