| 421 | ) |
| 422 | |
| 423 | def test_cookie_special_char(self): |
| 424 | response = self.fetch("/special_char") |
| 425 | headers = sorted(response.headers.get_list("Set-Cookie")) |
| 426 | self.assertEqual(len(headers), 3) |
| 427 | self.assertEqual(headers[0], 'equals="a=b"; Path=/') |
| 428 | self.assertEqual(headers[1], 'quote="a\\"b"; Path=/') |
| 429 | # Semicolons are octal-escaped |
| 430 | self.assertIn( |
| 431 | headers[2], |
| 432 | ('semicolon="a;b"; Path=/', 'semicolon="a\\073b"; Path=/'), |
| 433 | headers[2], |
| 434 | ) |
| 435 | |
| 436 | data = [ |
| 437 | ("foo=a=b", "a=b"), |
| 438 | ('foo="a=b"', "a=b"), |
| 439 | ('foo="a;b"', '"a'), # even quoted, ";" is a delimiter |
| 440 | ("foo=a\\073b", "a\\073b"), # escapes only decoded in quotes |
| 441 | ('foo="a\\073b"', "a;b"), |
| 442 | ('foo="a\\"b"', 'a"b'), |
| 443 | ] |
| 444 | for header, expected in data: |
| 445 | logging.debug("trying %r", header) |
| 446 | response = self.fetch("/get", headers={"Cookie": header}) |
| 447 | self.assertEqual(response.body, utf8(expected)) |
| 448 | |
| 449 | def test_set_cookie_forbidden_char(self): |
| 450 | response = self.fetch("/forbidden_char") |