173 lines
5.5 KiB
Python
173 lines
5.5 KiB
Python
import unittest
|
|
|
|
from .exceptions import InvalidHeaderFormat
|
|
from .headers import *
|
|
from .headers import build_basic_auth
|
|
|
|
|
|
class HeadersTests(unittest.TestCase):
|
|
|
|
def test_parse_connection(self):
|
|
for header, parsed in [
|
|
# Realistic use cases
|
|
(
|
|
'Upgrade', # Safari, Chrome
|
|
['Upgrade'],
|
|
),
|
|
(
|
|
'keep-alive, Upgrade', # Firefox
|
|
['keep-alive', 'Upgrade'],
|
|
),
|
|
# Pathological example
|
|
(
|
|
',,\t, , ,Upgrade ,,',
|
|
['Upgrade'],
|
|
),
|
|
]:
|
|
with self.subTest(header=header):
|
|
self.assertEqual(parse_connection(header), parsed)
|
|
|
|
def test_parse_connection_invalid_header(self):
|
|
for header in [
|
|
'???',
|
|
'keep-alive; Upgrade',
|
|
]:
|
|
with self.subTest(header=header):
|
|
with self.assertRaises(InvalidHeaderFormat):
|
|
parse_connection(header)
|
|
|
|
def test_parse_upgrade(self):
|
|
for header, parsed in [
|
|
# Realistic use case
|
|
(
|
|
'websocket',
|
|
['websocket'],
|
|
),
|
|
# Synthetic example
|
|
(
|
|
'http/3.0, websocket',
|
|
['http/3.0', 'websocket']
|
|
),
|
|
# Pathological example
|
|
(
|
|
',, WebSocket, \t,,',
|
|
['WebSocket'],
|
|
),
|
|
]:
|
|
with self.subTest(header=header):
|
|
self.assertEqual(parse_upgrade(header), parsed)
|
|
|
|
def test_parse_upgrade_invalid_header(self):
|
|
for header in [
|
|
'???',
|
|
'websocket 2',
|
|
'http/3.0; websocket',
|
|
]:
|
|
with self.subTest(header=header):
|
|
with self.assertRaises(InvalidHeaderFormat):
|
|
parse_upgrade(header)
|
|
|
|
def test_parse_extension_list(self):
|
|
for header, parsed in [
|
|
# Synthetic examples
|
|
(
|
|
'foo',
|
|
[('foo', [])],
|
|
),
|
|
(
|
|
'foo, bar',
|
|
[('foo', []), ('bar', [])],
|
|
),
|
|
(
|
|
'foo; name; token=token; quoted-string="quoted-string", '
|
|
'bar; quux; quuux',
|
|
[
|
|
('foo', [('name', None), ('token', 'token'),
|
|
('quoted-string', 'quoted-string')]),
|
|
('bar', [('quux', None), ('quuux', None)]),
|
|
],
|
|
),
|
|
# Pathological example
|
|
(
|
|
',\t, , ,foo ;bar = 42,, baz,,',
|
|
[('foo', [('bar', '42')]), ('baz', [])],
|
|
),
|
|
# Realistic use cases for permessage-deflate
|
|
(
|
|
'permessage-deflate',
|
|
[('permessage-deflate', [])],
|
|
),
|
|
(
|
|
'permessage-deflate; client_max_window_bits',
|
|
[('permessage-deflate', [('client_max_window_bits', None)])],
|
|
),
|
|
(
|
|
'permessage-deflate; server_max_window_bits=10',
|
|
[('permessage-deflate', [('server_max_window_bits', '10')])],
|
|
),
|
|
]:
|
|
with self.subTest(header=header):
|
|
self.assertEqual(parse_extension_list(header), parsed)
|
|
# Also ensure that build_extension_list round-trips cleanly.
|
|
unparsed = build_extension_list(parsed)
|
|
self.assertEqual(parse_extension_list(unparsed), parsed)
|
|
|
|
def test_parse_extension_list_invalid_header(self):
|
|
for header in [
|
|
# Truncated examples
|
|
'',
|
|
',\t,'
|
|
'foo;',
|
|
'foo; bar;',
|
|
'foo; bar=',
|
|
'foo; bar="baz',
|
|
# Wrong delimiter
|
|
'foo, bar, baz=quux; quuux',
|
|
# Value in quoted string parameter that isn't a token
|
|
'foo; bar=" "',
|
|
]:
|
|
with self.subTest(header=header):
|
|
with self.assertRaises(InvalidHeaderFormat):
|
|
parse_extension_list(header)
|
|
|
|
def test_parse_subprotocol_list(self):
|
|
for header, parsed in [
|
|
# Synthetic examples
|
|
(
|
|
'foo',
|
|
['foo'],
|
|
),
|
|
(
|
|
'foo, bar',
|
|
['foo', 'bar'],
|
|
),
|
|
# Pathological example
|
|
(
|
|
',\t, , ,foo ,, bar,baz,,',
|
|
['foo', 'bar', 'baz'],
|
|
),
|
|
]:
|
|
with self.subTest(header=header):
|
|
self.assertEqual(parse_subprotocol_list(header), parsed)
|
|
# Also ensure that build_subprotocol_list round-trips cleanly.
|
|
unparsed = build_subprotocol_list(parsed)
|
|
self.assertEqual(parse_subprotocol_list(unparsed), parsed)
|
|
|
|
def test_parse_subprotocol_list_invalid_header(self):
|
|
for header in [
|
|
# Truncated examples
|
|
'',
|
|
',\t,'
|
|
# Wrong delimiter
|
|
'foo; bar',
|
|
]:
|
|
with self.subTest(header=header):
|
|
with self.assertRaises(InvalidHeaderFormat):
|
|
parse_subprotocol_list(header)
|
|
|
|
def test_build_basic_auth(self):
|
|
# Test vector from RFC 7617.
|
|
self.assertEqual(
|
|
build_basic_auth("Aladdin", "open sesame"),
|
|
'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==',
|
|
)
|