test_cookie.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import time
  2. from datetime import datetime, timedelta
  3. from http import cookies
  4. from django.http import HttpResponse
  5. from django.test import SimpleTestCase
  6. from django.test.utils import freeze_time
  7. from django.utils.http import http_date
  8. from django.utils.timezone import utc
  9. class SetCookieTests(SimpleTestCase):
  10. def test_near_expiration(self):
  11. """Cookie will expire when a near expiration time is provided."""
  12. response = HttpResponse()
  13. # There's a timing weakness in this test; The expected result for
  14. # max-age requires that there be a very slight difference between the
  15. # evaluated expiration time and the time evaluated in set_cookie(). If
  16. # this difference doesn't exist, the cookie time will be 1 second
  17. # larger. The sleep guarantees that there will be a time difference.
  18. expires = datetime.utcnow() + timedelta(seconds=10)
  19. time.sleep(0.001)
  20. response.set_cookie('datetime', expires=expires)
  21. datetime_cookie = response.cookies['datetime']
  22. self.assertEqual(datetime_cookie['max-age'], 10)
  23. def test_aware_expiration(self):
  24. """set_cookie() accepts an aware datetime as expiration time."""
  25. response = HttpResponse()
  26. expires = (datetime.utcnow() + timedelta(seconds=10)).replace(tzinfo=utc)
  27. time.sleep(0.001)
  28. response.set_cookie('datetime', expires=expires)
  29. datetime_cookie = response.cookies['datetime']
  30. self.assertEqual(datetime_cookie['max-age'], 10)
  31. def test_create_cookie_after_deleting_cookie(self):
  32. """Setting a cookie after deletion clears the expiry date."""
  33. response = HttpResponse()
  34. response.set_cookie('c', 'old-value')
  35. self.assertEqual(response.cookies['c']['expires'], '')
  36. response.delete_cookie('c')
  37. self.assertEqual(response.cookies['c']['expires'], 'Thu, 01 Jan 1970 00:00:00 GMT')
  38. response.set_cookie('c', 'new-value')
  39. self.assertEqual(response.cookies['c']['expires'], '')
  40. def test_far_expiration(self):
  41. """Cookie will expire when a distant expiration time is provided."""
  42. response = HttpResponse()
  43. response.set_cookie('datetime', expires=datetime(2028, 1, 1, 4, 5, 6))
  44. datetime_cookie = response.cookies['datetime']
  45. self.assertIn(
  46. datetime_cookie['expires'],
  47. # assertIn accounts for slight time dependency (#23450)
  48. ('Sat, 01 Jan 2028 04:05:06 GMT', 'Sat, 01 Jan 2028 04:05:07 GMT')
  49. )
  50. def test_max_age_expiration(self):
  51. """Cookie will expire if max_age is provided."""
  52. response = HttpResponse()
  53. set_cookie_time = time.time()
  54. with freeze_time(set_cookie_time):
  55. response.set_cookie('max_age', max_age=10)
  56. max_age_cookie = response.cookies['max_age']
  57. self.assertEqual(max_age_cookie['max-age'], 10)
  58. self.assertEqual(max_age_cookie['expires'], http_date(set_cookie_time + 10))
  59. def test_httponly_cookie(self):
  60. response = HttpResponse()
  61. response.set_cookie('example', httponly=True)
  62. example_cookie = response.cookies['example']
  63. self.assertIn('; %s' % cookies.Morsel._reserved['httponly'], str(example_cookie))
  64. self.assertIs(example_cookie['httponly'], True)
  65. def test_unicode_cookie(self):
  66. """HttpResponse.set_cookie() works with unicode data."""
  67. response = HttpResponse()
  68. cookie_value = '清風'
  69. response.set_cookie('test', cookie_value)
  70. self.assertEqual(response.cookies['test'].value, cookie_value)
  71. def test_samesite(self):
  72. response = HttpResponse()
  73. response.set_cookie('example', samesite='Lax')
  74. self.assertEqual(response.cookies['example']['samesite'], 'Lax')
  75. response.set_cookie('example', samesite='strict')
  76. self.assertEqual(response.cookies['example']['samesite'], 'strict')
  77. def test_invalid_samesite(self):
  78. with self.assertRaisesMessage(ValueError, 'samesite must be "lax" or "strict".'):
  79. HttpResponse().set_cookie('example', samesite='invalid')
  80. class DeleteCookieTests(SimpleTestCase):
  81. def test_default(self):
  82. response = HttpResponse()
  83. response.delete_cookie('c')
  84. cookie = response.cookies['c']
  85. self.assertEqual(cookie['expires'], 'Thu, 01 Jan 1970 00:00:00 GMT')
  86. self.assertEqual(cookie['max-age'], 0)
  87. self.assertEqual(cookie['path'], '/')
  88. self.assertEqual(cookie['secure'], '')
  89. self.assertEqual(cookie['domain'], '')
  90. def test_delete_cookie_secure_prefix(self):
  91. """
  92. delete_cookie() sets the secure flag if the cookie name starts with
  93. __Host- or __Secure- (without that, browsers ignore cookies with those
  94. prefixes).
  95. """
  96. response = HttpResponse()
  97. for prefix in ('Secure', 'Host'):
  98. with self.subTest(prefix=prefix):
  99. cookie_name = '__%s-c' % prefix
  100. response.delete_cookie(cookie_name)
  101. self.assertEqual(response.cookies[cookie_name]['secure'], True)