123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601 |
- # Copyright (c) Twisted Matrix Laboratories.
- # See LICENSE for details.
- """
- Tests for L{twisted.web.http_headers}.
- """
- from __future__ import division, absolute_import
- from twisted.trial.unittest import TestCase
- from twisted.python.compat import _PY3, unicode
- from twisted.web.http_headers import Headers
- class BytesHeadersTests(TestCase):
- """
- Tests for L{Headers}, using L{bytes} arguments for methods.
- """
- def test_initializer(self):
- """
- The header values passed to L{Headers.__init__} can be retrieved via
- L{Headers.getRawHeaders}.
- """
- h = Headers({b'Foo': [b'bar']})
- self.assertEqual(h.getRawHeaders(b'foo'), [b'bar'])
- def test_setRawHeaders(self):
- """
- L{Headers.setRawHeaders} sets the header values for the given
- header name to the sequence of byte string values.
- """
- rawValue = [b"value1", b"value2"]
- h = Headers()
- h.setRawHeaders(b"test", rawValue)
- self.assertTrue(h.hasHeader(b"test"))
- self.assertTrue(h.hasHeader(b"Test"))
- self.assertEqual(h.getRawHeaders(b"test"), rawValue)
- def test_rawHeadersTypeChecking(self):
- """
- L{Headers.setRawHeaders} requires values to be of type list.
- """
- h = Headers()
- self.assertRaises(TypeError, h.setRawHeaders, b'key', {b'Foo': b'bar'})
- def test_addRawHeader(self):
- """
- L{Headers.addRawHeader} adds a new value for a given header.
- """
- h = Headers()
- h.addRawHeader(b"test", b"lemur")
- self.assertEqual(h.getRawHeaders(b"test"), [b"lemur"])
- h.addRawHeader(b"test", b"panda")
- self.assertEqual(h.getRawHeaders(b"test"), [b"lemur", b"panda"])
- def test_getRawHeadersNoDefault(self):
- """
- L{Headers.getRawHeaders} returns L{None} if the header is not found and
- no default is specified.
- """
- self.assertIsNone(Headers().getRawHeaders(b"test"))
- def test_getRawHeadersDefaultValue(self):
- """
- L{Headers.getRawHeaders} returns the specified default value when no
- header is found.
- """
- h = Headers()
- default = object()
- self.assertIdentical(h.getRawHeaders(b"test", default), default)
- def test_getRawHeadersWithDefaultMatchingValue(self):
- """
- If the object passed as the value list to L{Headers.setRawHeaders}
- is later passed as a default to L{Headers.getRawHeaders}, the
- result nevertheless contains encoded values.
- """
- h = Headers()
- default = [u"value"]
- h.setRawHeaders(b"key", default)
- self.assertIsInstance(h.getRawHeaders(b"key", default)[0], bytes)
- self.assertEqual(h.getRawHeaders(b"key", default), [b"value"])
- def test_getRawHeaders(self):
- """
- L{Headers.getRawHeaders} returns the values which have been set for a
- given header.
- """
- h = Headers()
- h.setRawHeaders(b"test", [b"lemur"])
- self.assertEqual(h.getRawHeaders(b"test"), [b"lemur"])
- self.assertEqual(h.getRawHeaders(b"Test"), [b"lemur"])
- def test_hasHeaderTrue(self):
- """
- Check that L{Headers.hasHeader} returns C{True} when the given header
- is found.
- """
- h = Headers()
- h.setRawHeaders(b"test", [b"lemur"])
- self.assertTrue(h.hasHeader(b"test"))
- self.assertTrue(h.hasHeader(b"Test"))
- def test_hasHeaderFalse(self):
- """
- L{Headers.hasHeader} returns C{False} when the given header is not
- found.
- """
- self.assertFalse(Headers().hasHeader(b"test"))
- def test_removeHeader(self):
- """
- Check that L{Headers.removeHeader} removes the given header.
- """
- h = Headers()
- h.setRawHeaders(b"foo", [b"lemur"])
- self.assertTrue(h.hasHeader(b"foo"))
- h.removeHeader(b"foo")
- self.assertFalse(h.hasHeader(b"foo"))
- h.setRawHeaders(b"bar", [b"panda"])
- self.assertTrue(h.hasHeader(b"bar"))
- h.removeHeader(b"Bar")
- self.assertFalse(h.hasHeader(b"bar"))
- def test_removeHeaderDoesntExist(self):
- """
- L{Headers.removeHeader} is a no-operation when the specified header is
- not found.
- """
- h = Headers()
- h.removeHeader(b"test")
- self.assertEqual(list(h.getAllRawHeaders()), [])
- def test_canonicalNameCaps(self):
- """
- L{Headers._canonicalNameCaps} returns the canonical capitalization for
- the given header.
- """
- h = Headers()
- self.assertEqual(h._canonicalNameCaps(b"test"), b"Test")
- self.assertEqual(h._canonicalNameCaps(b"test-stuff"), b"Test-Stuff")
- self.assertEqual(h._canonicalNameCaps(b"content-md5"), b"Content-MD5")
- self.assertEqual(h._canonicalNameCaps(b"dnt"), b"DNT")
- self.assertEqual(h._canonicalNameCaps(b"etag"), b"ETag")
- self.assertEqual(h._canonicalNameCaps(b"p3p"), b"P3P")
- self.assertEqual(h._canonicalNameCaps(b"te"), b"TE")
- self.assertEqual(h._canonicalNameCaps(b"www-authenticate"),
- b"WWW-Authenticate")
- self.assertEqual(h._canonicalNameCaps(b"x-xss-protection"),
- b"X-XSS-Protection")
- def test_getAllRawHeaders(self):
- """
- L{Headers.getAllRawHeaders} returns an iterable of (k, v) pairs, where
- C{k} is the canonicalized representation of the header name, and C{v}
- is a sequence of values.
- """
- h = Headers()
- h.setRawHeaders(b"test", [b"lemurs"])
- h.setRawHeaders(b"www-authenticate", [b"basic aksljdlk="])
- allHeaders = set([(k, tuple(v)) for k, v in h.getAllRawHeaders()])
- self.assertEqual(allHeaders,
- set([(b"WWW-Authenticate", (b"basic aksljdlk=",)),
- (b"Test", (b"lemurs",))]))
- def test_headersComparison(self):
- """
- A L{Headers} instance compares equal to itself and to another
- L{Headers} instance with the same values.
- """
- first = Headers()
- first.setRawHeaders(b"foo", [b"panda"])
- second = Headers()
- second.setRawHeaders(b"foo", [b"panda"])
- third = Headers()
- third.setRawHeaders(b"foo", [b"lemur", b"panda"])
- self.assertEqual(first, first)
- self.assertEqual(first, second)
- self.assertNotEqual(first, third)
- def test_otherComparison(self):
- """
- An instance of L{Headers} does not compare equal to other unrelated
- objects.
- """
- h = Headers()
- self.assertNotEqual(h, ())
- self.assertNotEqual(h, object())
- self.assertNotEqual(h, b"foo")
- def test_repr(self):
- """
- The L{repr} of a L{Headers} instance shows the names and values of all
- the headers it contains.
- """
- foo = b"foo"
- bar = b"bar"
- baz = b"baz"
- self.assertEqual(
- repr(Headers({foo: [bar, baz]})),
- "Headers({%r: [%r, %r]})" % (foo, bar, baz))
- def test_reprWithRawBytes(self):
- """
- The L{repr} of a L{Headers} instance shows the names and values of all
- the headers it contains, not attempting to decode any raw bytes.
- """
- # There's no such thing as undecodable latin-1, you'll just get
- # some mojibake
- foo = b"foo"
- # But this is invalid UTF-8! So, any accidental decoding/encoding will
- # throw an exception.
- bar = b"bar\xe1"
- baz = b"baz\xe1"
- self.assertEqual(
- repr(Headers({foo: [bar, baz]})),
- "Headers({%r: [%r, %r]})" % (foo, bar, baz))
- def test_subclassRepr(self):
- """
- The L{repr} of an instance of a subclass of L{Headers} uses the name
- of the subclass instead of the string C{"Headers"}.
- """
- foo = b"foo"
- bar = b"bar"
- baz = b"baz"
- class FunnyHeaders(Headers):
- pass
- self.assertEqual(
- repr(FunnyHeaders({foo: [bar, baz]})),
- "FunnyHeaders({%r: [%r, %r]})" % (foo, bar, baz))
- def test_copy(self):
- """
- L{Headers.copy} creates a new independent copy of an existing
- L{Headers} instance, allowing future modifications without impacts
- between the copies.
- """
- h = Headers()
- h.setRawHeaders(b'test', [b'foo'])
- i = h.copy()
- self.assertEqual(i.getRawHeaders(b'test'), [b'foo'])
- h.addRawHeader(b'test', b'bar')
- self.assertEqual(i.getRawHeaders(b'test'), [b'foo'])
- i.addRawHeader(b'test', b'baz')
- self.assertEqual(h.getRawHeaders(b'test'), [b'foo', b'bar'])
- class UnicodeHeadersTests(TestCase):
- """
- Tests for L{Headers}, using L{unicode} arguments for methods.
- """
- def test_initializer(self):
- """
- The header values passed to L{Headers.__init__} can be retrieved via
- L{Headers.getRawHeaders}. If a L{bytes} argument is given, it returns
- L{bytes} values, and if a L{unicode} argument is given, it returns
- L{unicode} values. Both are the same header value, just encoded or
- decoded.
- """
- h = Headers({u'Foo': [u'bar']})
- self.assertEqual(h.getRawHeaders(b'foo'), [b'bar'])
- self.assertEqual(h.getRawHeaders(u'foo'), [u'bar'])
- def test_setRawHeaders(self):
- """
- L{Headers.setRawHeaders} sets the header values for the given
- header name to the sequence of strings, encoded.
- """
- rawValue = [u"value1", u"value2"]
- rawEncodedValue = [b"value1", b"value2"]
- h = Headers()
- h.setRawHeaders("test", rawValue)
- self.assertTrue(h.hasHeader(b"test"))
- self.assertTrue(h.hasHeader(b"Test"))
- self.assertTrue(h.hasHeader("test"))
- self.assertTrue(h.hasHeader("Test"))
- self.assertEqual(h.getRawHeaders("test"), rawValue)
- self.assertEqual(h.getRawHeaders(b"test"), rawEncodedValue)
- def test_nameNotEncodable(self):
- """
- Passing L{unicode} to any function that takes a header name will encode
- said header name as ISO-8859-1, and if it cannot be encoded, it will
- raise a L{UnicodeDecodeError}.
- """
- h = Headers()
- # Only these two functions take names
- with self.assertRaises(UnicodeEncodeError):
- h.setRawHeaders(u"\u2603", [u"val"])
- with self.assertRaises(UnicodeEncodeError):
- h.hasHeader(u"\u2603")
- def test_nameEncoding(self):
- """
- Passing L{unicode} to any function that takes a header name will encode
- said header name as ISO-8859-1.
- """
- h = Headers()
- # We set it using a Unicode string.
- h.setRawHeaders(u"\u00E1", [b"foo"])
- # It's encoded to the ISO-8859-1 value, which we can use to access it
- self.assertTrue(h.hasHeader(b"\xe1"))
- self.assertEqual(h.getRawHeaders(b"\xe1"), [b'foo'])
- # We can still access it using the Unicode string..
- self.assertTrue(h.hasHeader(u"\u00E1"))
- def test_rawHeadersValueEncoding(self):
- """
- Passing L{unicode} to L{Headers.setRawHeaders} will encode the name as
- ISO-8859-1 and values as UTF-8.
- """
- h = Headers()
- h.setRawHeaders(u"\u00E1", [u"\u2603", b"foo"])
- self.assertTrue(h.hasHeader(b"\xe1"))
- self.assertEqual(h.getRawHeaders(b"\xe1"), [b'\xe2\x98\x83', b'foo'])
- def test_rawHeadersTypeChecking(self):
- """
- L{Headers.setRawHeaders} requires values to be of type list.
- """
- h = Headers()
- self.assertRaises(TypeError, h.setRawHeaders, u'key', {u'Foo': u'bar'})
- def test_addRawHeader(self):
- """
- L{Headers.addRawHeader} adds a new value for a given header.
- """
- h = Headers()
- h.addRawHeader(u"test", u"lemur")
- self.assertEqual(h.getRawHeaders(u"test"), [u"lemur"])
- h.addRawHeader(u"test", u"panda")
- self.assertEqual(h.getRawHeaders(u"test"), [u"lemur", u"panda"])
- self.assertEqual(h.getRawHeaders(b"test"), [b"lemur", b"panda"])
- def test_getRawHeadersNoDefault(self):
- """
- L{Headers.getRawHeaders} returns L{None} if the header is not found and
- no default is specified.
- """
- self.assertIsNone(Headers().getRawHeaders(u"test"))
- def test_getRawHeadersDefaultValue(self):
- """
- L{Headers.getRawHeaders} returns the specified default value when no
- header is found.
- """
- h = Headers()
- default = object()
- self.assertIdentical(h.getRawHeaders(u"test", default), default)
- self.assertIdentical(h.getRawHeaders(u"test", None), None)
- self.assertEqual(h.getRawHeaders(u"test", [None]), [None])
- self.assertEqual(
- h.getRawHeaders(u"test", [u"\N{SNOWMAN}"]),
- [u"\N{SNOWMAN}"],
- )
- def test_getRawHeadersWithDefaultMatchingValue(self):
- """
- If the object passed as the value list to L{Headers.setRawHeaders}
- is later passed as a default to L{Headers.getRawHeaders}, the
- result nevertheless contains decoded values.
- """
- h = Headers()
- default = [b"value"]
- h.setRawHeaders(b"key", default)
- self.assertIsInstance(h.getRawHeaders(u"key", default)[0], unicode)
- self.assertEqual(h.getRawHeaders(u"key", default), [u"value"])
- def test_getRawHeaders(self):
- """
- L{Headers.getRawHeaders} returns the values which have been set for a
- given header.
- """
- h = Headers()
- h.setRawHeaders(u"test\u00E1", [u"lemur"])
- self.assertEqual(h.getRawHeaders(u"test\u00E1"), [u"lemur"])
- self.assertEqual(h.getRawHeaders(u"Test\u00E1"), [u"lemur"])
- self.assertEqual(h.getRawHeaders(b"test\xe1"), [b"lemur"])
- self.assertEqual(h.getRawHeaders(b"Test\xe1"), [b"lemur"])
- def test_hasHeaderTrue(self):
- """
- Check that L{Headers.hasHeader} returns C{True} when the given header
- is found.
- """
- h = Headers()
- h.setRawHeaders(u"test\u00E1", [u"lemur"])
- self.assertTrue(h.hasHeader(u"test\u00E1"))
- self.assertTrue(h.hasHeader(u"Test\u00E1"))
- self.assertTrue(h.hasHeader(b"test\xe1"))
- self.assertTrue(h.hasHeader(b"Test\xe1"))
- def test_hasHeaderFalse(self):
- """
- L{Headers.hasHeader} returns C{False} when the given header is not
- found.
- """
- self.assertFalse(Headers().hasHeader(u"test\u00E1"))
- def test_removeHeader(self):
- """
- Check that L{Headers.removeHeader} removes the given header.
- """
- h = Headers()
- h.setRawHeaders(u"foo", [u"lemur"])
- self.assertTrue(h.hasHeader(u"foo"))
- h.removeHeader(u"foo")
- self.assertFalse(h.hasHeader(u"foo"))
- self.assertFalse(h.hasHeader(b"foo"))
- h.setRawHeaders(u"bar", [u"panda"])
- self.assertTrue(h.hasHeader(u"bar"))
- h.removeHeader(u"Bar")
- self.assertFalse(h.hasHeader(u"bar"))
- self.assertFalse(h.hasHeader(b"bar"))
- def test_removeHeaderDoesntExist(self):
- """
- L{Headers.removeHeader} is a no-operation when the specified header is
- not found.
- """
- h = Headers()
- h.removeHeader(u"test")
- self.assertEqual(list(h.getAllRawHeaders()), [])
- def test_getAllRawHeaders(self):
- """
- L{Headers.getAllRawHeaders} returns an iterable of (k, v) pairs, where
- C{k} is the canonicalized representation of the header name, and C{v}
- is a sequence of values.
- """
- h = Headers()
- h.setRawHeaders(u"test\u00E1", [u"lemurs"])
- h.setRawHeaders(u"www-authenticate", [u"basic aksljdlk="])
- h.setRawHeaders(u"content-md5", [u"kjdfdfgdfgnsd"])
- allHeaders = set([(k, tuple(v)) for k, v in h.getAllRawHeaders()])
- self.assertEqual(allHeaders,
- set([(b"WWW-Authenticate", (b"basic aksljdlk=",)),
- (b"Content-MD5", (b"kjdfdfgdfgnsd",)),
- (b"Test\xe1", (b"lemurs",))]))
- def test_headersComparison(self):
- """
- A L{Headers} instance compares equal to itself and to another
- L{Headers} instance with the same values.
- """
- first = Headers()
- first.setRawHeaders(u"foo\u00E1", [u"panda"])
- second = Headers()
- second.setRawHeaders(u"foo\u00E1", [u"panda"])
- third = Headers()
- third.setRawHeaders(u"foo\u00E1", [u"lemur", u"panda"])
- self.assertEqual(first, first)
- self.assertEqual(first, second)
- self.assertNotEqual(first, third)
- # Headers instantiated with bytes equivs are also the same
- firstBytes = Headers()
- firstBytes.setRawHeaders(b"foo\xe1", [b"panda"])
- secondBytes = Headers()
- secondBytes.setRawHeaders(b"foo\xe1", [b"panda"])
- thirdBytes = Headers()
- thirdBytes.setRawHeaders(b"foo\xe1", [b"lemur", u"panda"])
- self.assertEqual(first, firstBytes)
- self.assertEqual(second, secondBytes)
- self.assertEqual(third, thirdBytes)
- def test_otherComparison(self):
- """
- An instance of L{Headers} does not compare equal to other unrelated
- objects.
- """
- h = Headers()
- self.assertNotEqual(h, ())
- self.assertNotEqual(h, object())
- self.assertNotEqual(h, u"foo")
- def test_repr(self):
- """
- The L{repr} of a L{Headers} instance shows the names and values of all
- the headers it contains. This shows only reprs of bytes values, as
- undecodable headers may cause an exception.
- """
- foo = u"foo\u00E1"
- bar = u"bar\u2603"
- baz = u"baz"
- fooEncoded = "'foo\\xe1'"
- barEncoded = "'bar\\xe2\\x98\\x83'"
- if _PY3:
- fooEncoded = "b" + fooEncoded
- barEncoded = "b" + barEncoded
- self.assertEqual(
- repr(Headers({foo: [bar, baz]})),
- "Headers({%s: [%s, %r]})" % (fooEncoded,
- barEncoded,
- baz.encode('utf8')))
- def test_subclassRepr(self):
- """
- The L{repr} of an instance of a subclass of L{Headers} uses the name
- of the subclass instead of the string C{"Headers"}.
- """
- foo = u"foo\u00E1"
- bar = u"bar\u2603"
- baz = u"baz"
- fooEncoded = "'foo\\xe1'"
- barEncoded = "'bar\\xe2\\x98\\x83'"
- if _PY3:
- fooEncoded = "b" + fooEncoded
- barEncoded = "b" + barEncoded
- class FunnyHeaders(Headers):
- pass
- self.assertEqual(
- repr(FunnyHeaders({foo: [bar, baz]})),
- "FunnyHeaders({%s: [%s, %r]})" % (fooEncoded,
- barEncoded,
- baz.encode('utf8')))
- def test_copy(self):
- """
- L{Headers.copy} creates a new independent copy of an existing
- L{Headers} instance, allowing future modifications without impacts
- between the copies.
- """
- h = Headers()
- h.setRawHeaders(u'test\u00E1', [u'foo\u2603'])
- i = h.copy()
- # The copy contains the same value as the original
- self.assertEqual(i.getRawHeaders(u'test\u00E1'), [u'foo\u2603'])
- self.assertEqual(i.getRawHeaders(b'test\xe1'), [b'foo\xe2\x98\x83'])
- # Add a header to the original
- h.addRawHeader(u'test\u00E1', u'bar')
- # Verify that the copy has not changed
- self.assertEqual(i.getRawHeaders(u'test\u00E1'), [u'foo\u2603'])
- self.assertEqual(i.getRawHeaders(b'test\xe1'), [b'foo\xe2\x98\x83'])
- # Add a header to the copy
- i.addRawHeader(u'test\u00E1', b'baz')
- # Verify that the orignal does not have it
- self.assertEqual(
- h.getRawHeaders(u'test\u00E1'), [u'foo\u2603', u'bar'])
- self.assertEqual(
- h.getRawHeaders(b'test\xe1'), [b'foo\xe2\x98\x83', b'bar'])
|