{
"command": "git diff bottle.py | head -500",
"description": "Show diff of bottle.py"
}diff --git a/bottle.py b/bottle.py
index a297ca9..d1e4022 100755
--- a/bottle.py
+++ b/bottle.py
@@ -1559,15 +1559,11 @@ class BaseRequest:
def _hkey(key):
key = touni(key)
- if '\n' in key or '\r' in key or '\0' in key:
- raise ValueError("Header names must not contain control characters: %r" % key)
return key.title().replace('_', '-')
def _hval(value):
value = touni(value)
- if '\n' in value or '\r' in value or '\0' in value:
- raise ValueError("Header value must not contain control characters: %r" % value)
return value
[stdout]
diff --git a/bottle.py b/bottle.py
index a297ca9..d1e4022 100755
--- a/bottle.py
+++ b/bottle.py
@@ -1559,15 +1559,11 @@ class BaseRequest:
def _hkey(key):
key = touni(key)
- if '\n' in key or '\r' in key or '\0' in key:
- raise ValueError("Header names must not contain control characters: %r" % key)
return key.title().replace('_', '-')
def _hval(value):
value = touni(value)
- if '\n' in value or '\r' in value or '\0' in value:
- raise ValueError("Header value must not contain control characters: %r" % value)
return value
[metadata] {"noOutputExpected": false}{
"command": "git status && git diff --stat && ls -la",
"description": "Check git status and repo contents"
}On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: bottle.py
no changes added to commit (use "git add" and/or "git commit -a")
bottle.py | 4 ----
1 file changed, 4 deletions(-)
total 208
drwxr-xr-x 1 root root 26 Oct 28 2025 .
drwxr-xr-x 1 root root 159 Sep 26 02:14 ..
drwxr-xr-x 1 root root 27 Sep 26 02:15 .git
drwxr-xr-x 3 root root 54 Oct 28 2025 .github
-rw-r--r-- 1 root root 188 Oct 28 2025 .gitignore
-rw-r--r-- 1 root root 634 Oct 28 2025 .readthedocs.yaml
-rw-r--r-- 1 root root 1328 Oct 28 2025 AUTHORS
-rw-r--r-- 1 root root 1066 Oct 28 2025 LICENSE
-rw-r--r-- 1 root root 1112 Oct 28 2025 Makefile
-rw-r--r-- 1 root root 2846 Oct 28 2025 README.rst
-rwxr-xr-x 1 root root 175565 Oct 28 2025 bottle.py
drwxr-xr-x 4 root root 4096 Oct 28 2025 docs
-rw-r--r-- 1 root root 1741 Oct 28 2025 pyproject.toml
drwxr-xr-x 3 root root 4096 Oct 28 2025 test
[stdout]
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: bottle.py
no changes added to commit (use "git add" and/or "git commit -a")
bottle.py | 4 ----
1 file changed, 4 deletions(-)
total 208
drwxr-xr-x 1 root root 26 Oct 28 2025 .
drwxr-xr-x 1 root root 159 Sep 26 02:14 ..
drwxr-xr-x 1 root root 27 Sep 26 02:15 .git
drwxr-xr-x 3 root root 54 Oct 28 2025 .github
-rw-r--r-- 1 root root 188 Oct 28 2025 .gitignore
-rw-r--r-- 1 root root 634 Oct 28 2025 .readthedocs.yaml
-rw-r--r-- 1 root root 1328 Oct 28 2025 AUTHORS
-rw-r--r-- 1 root root 1066 Oct 28 2025 LICENSE
-rw-r--r-- 1 root root 1112 Oct 28 2025 Makefile
-rw-r--r-- 1 root root 2846 Oct 28 2025 README.rst
-rwxr-xr-x 1 root root 175565 Oct 28 2025 bottle.py
drwxr-xr-x 4 root root 4096 Oct 28 2025 docs
-rw-r--r-- 1 root root 1741 Oct 28 2025 pyproject.toml
drwxr-xr-x 3 root root 4096 Oct 28 2025 test
[metadata] {"noOutputExpected": false}{
"file_path": "/app/bottle.py",
"offset": 1540,
"limit": 50
}1540 var = self.environ['bottle.request.ext.%s' % name]
1541 return var.__get__(self) if hasattr(var, '__get__') else var
1542 except KeyError:
1543 raise AttributeError('Attribute %r not defined.' % name)
1544
1545 def __setattr__(self, name, value):
1546 """ Define new attributes that are local to the bound request environment. """
1547 if name == 'environ': return object.__setattr__(self, name, value)
1548 key = 'bottle.request.ext.%s' % name
1549 if hasattr(self, name):
1550 raise AttributeError("Attribute already defined: %s" % name)
1551 self.environ[key] = value
1552
1553 def __delattr__(self, name):
1554 try:
1555 del self.environ['bottle.request.ext.%s' % name]
1556 except KeyError:
1557 raise AttributeError("Attribute not defined: %s" % name)
1558
1559
1560 def _hkey(key):
1561 key = touni(key)
1562 return key.title().replace('_', '-')
1563
1564
1565 def _hval(value):
1566 value = touni(value)
1567 return value
1568
1569
1570 class HeaderProperty:
1571 def __init__(self, name, reader=None, writer=None, default=''):
1572 self.name, self.default = name, default
1573 self.reader, self.writer = reader, writer
1574 self.__doc__ = 'Current value of the %r header.' % name.title()
1575
1576 def __get__(self, obj, _):
1577 if obj is None: return self
1578 value = obj.get_header(self.name, self.default)
1579 return self.reader(value) if self.reader else value
1580
1581 def __set__(self, obj, value):
1582 obj[self.name] = self.writer(value) if self.writer else value
1583
1584 def __delete__(self, obj):
1585 del obj[self.name]
1586
1587
1588 class BaseResponse:
1589 """ Storage class for a response body as well as headers and cookies.
[metadata] {"type": "text", "file": {"filePath": "/app/bottle.py", "content": " var = self.environ['bottle.request.ext.%s' % name]\n return var.__get__(self) if hasattr(var, '__get__') else var\n except KeyError:\n raise AttributeError('Attribute %r not defined.' % name)\n\n def __setattr__(self, name, value):\n \"\"\" Define new attributes that are local to the bound request environment. \"\"\"\n if name == 'environ': return object.__setattr__(self, name, value)\n key = 'bottle.request.ext.%s' % name\n if hasattr(self, name):\n raise AttributeError(\"Attribute already defined: %s\" % name)\n self.environ[key] = value\n\n def __delattr__(self, name):\n try:\n del self.environ['bottle.request.ext.%s' % name]\n except KeyError:\n raise AttributeError(\"Attribute not defined: %s\" % name)\n\n\ndef _hkey(key):\n key = touni(key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n return value\n\n\nclass HeaderProperty:\n def __init__(self, name, reader=None, writer=None, default=''):\n self.name, self.default = name, default\n self.reader, self.writer = reader, writer\n self.__doc__ = 'Current value of the %r header.' % name.title()\n\n def __get__(self, obj, _):\n if obj is None: return self\n value = obj.get_header(self.name, self.default)\n return self.reader(value) if self.reader else value\n\n def __set__(self, obj, value):\n obj[self.name] = self.writer(value) if self.writer else value\n\n def __delete__(self, obj):\n del obj[self.name]\n\n\nclass BaseResponse:\n \"\"\" Storage class for a response body as well as headers and cookies.", "numLines": 50, "startLine": 1540, "totalLines": 4577}}{
"command": "grep -n -i -E \"hkey|hval|control character|CRLF|\\\\\\\\r|\\\\\\\\n|header\" test/test_wsgi.py test/test_environ.py 2>/dev/null | head -80",
"description": "Search tests for header/CRLF related tests"
}test/test_wsgi.py:53: """ 204 responses must not return some entity headers """
test/test_wsgi.py:56: bottle.response.set_header(h, 'foo')
test/test_wsgi.py:58: for h, v in bottle.response.headerlist:
test/test_wsgi.py:59: self.assertFalse(h.lower() in bad, "Header %s not deleted" % h)
test/test_wsgi.py:62: """ 304 responses must not return entity headers """
test/test_wsgi.py:67: bottle.response.set_header(h, 'foo')
test/test_wsgi.py:69: for h, v in bottle.response.headerlist:
test/test_wsgi.py:70: self.assertFalse(h.lower() in bad, "Header %s not deleted" % h)
test/test_wsgi.py:105: def test_utf8_header(self):
test/test_wsgi.py:106: header = 'öäü'.encode('utf8').decode('latin1')
test/test_wsgi.py:109: h = bottle.request.get_header('X-Test')
test/test_wsgi.py:111: bottle.response.set_header('X-Test', h)
test/test_wsgi.py:112: self.assertHeader('X-Test', header, '/test', env={'HTTP_X_TEST': header})
test/test_wsgi.py:137: self.assertHeader('Location', 'http://127.0.0.1/yes', '/', env=env)
test/test_wsgi.py:140: self.assertHeader('Location', 'http://127.0.0.1/yes', '/', env=env)
test/test_wsgi.py:142: self.assertHeader('Location', 'http://127.0.0.1/yes', '/one', env=env)
test/test_wsgi.py:147: bottle.response.headers['Test-Header'] = 'test'
test/test_wsgi.py:152: bottle.response.headers['Test-Header'] = 'test'
test/test_wsgi.py:154: self.assertHeader('Test-Header', 'test', '/yield')
test/test_wsgi.py:156: self.assertHeader('Test-Header', 'test', '/yield_nothing')
test/test_wsgi.py:166: c = self.urlopen('/cookie')['header'].get_all('Set-Cookie', '')
test/test_wsgi.py:168: c = self.urlopen('/cookie')['header'].get('Set-Cookie', '').split(',')
test/test_wsgi.py:332: bottle.response.headers['X-Hook'] = 'after'
test/test_wsgi.py:334: self.assertHeader('X-Hook', 'after', '/test')
test/test_wsgi.py:410: def test_after_response_hook_can_set_headers(self):
test/test_wsgi.py:425: bottle.response.headers["X-Hook"] = 'works'
test/test_wsgi.py:429: self.assertHeader('X-Hook', 'works', route)
test/test_wsgi.py:466: result = '+base+\n+main+\n!1234!\n+include+\n-main-\n+include+\n-base-\n'
test/test_wsgi.py:467: self.assertHeader('Content-Type', 'text/html; charset=UTF-8', '/tpl')
test/test_environ.py:129: def test_header_access(self):
test/test_environ.py:130: """ Environ: Request objects decode headers """
test/test_environ.py:133: e['HTTP_SOME_HEADER'] = 'some value'
test/test_environ.py:135: request['HTTP_SOME_OTHER_HEADER'] = 'some other value'
test/test_environ.py:136: self.assertTrue('Some-Header' in request.headers)
test/test_environ.py:137: self.assertTrue(request.headers['Some-Header'] == 'some value')
test/test_environ.py:138: self.assertTrue(request.headers['Some-Other-Header'] == 'some other value')
test/test_environ.py:140: def test_header_access_special(self):
test/test_environ.py:146: self.assertEqual(request.headers['Content-Type'], 'test')
test/test_environ.py:147: self.assertEqual(request.headers['Content-Length'], '123')
test/test_environ.py:298: self._test_chunked('1\r\nx\r\nff\r\n' + 'y'*255 + '\r\n0\r\n',
test/test_environ.py:300: self._test_chunked('8\r\nxxxxxxxx\r\n0\r\n','xxxxxxxx')
test/test_environ.py:301: self._test_chunked('0\r\n', '')
test/test_environ.py:304: self._test_chunked('8 ; foo\r\nxxxxxxxx\r\n0\r\n','xxxxxxxx')
test/test_environ.py:305: self._test_chunked('8;foo\r\nxxxxxxxx\r\n0\r\n','xxxxxxxx')
test/test_environ.py:306: self._test_chunked('8;foo=bar\r\nxxxxxxxx\r\n0\r\n','xxxxxxxx')
test/test_environ.py:309: self._test_chunked('1\r\nx\r\n', HTTPError)
test/test_environ.py:312: self._test_chunked('2\r\nx\r\n', HTTPError)
test/test_environ.py:315: self._test_chunked('x\r\nx\r\n', HTTPError)
test/test_environ.py:323: files = [('file1','filename1.txt','content1'), ('万难','万难foo.py', 'ä\nö\rü')]
test/test_environ.py:343: self.assertEqual(tob('ä\nö\rü'), x)
test/test_environ.py:364: def test_json_noheader(self):
test/test_environ.py:365: """ Environ: Request.json property with missing content-type header. """
test/test_environ.py:394: def test_json_forged_header_issue616(self):
test/test_environ.py:403: def test_json_header_empty_body(self):
test/test_environ.py:493: def test_constructor_headerlist(self):
test/test_environ.py:499: def test_wsgi_header_values(self):
test/test_environ.py:502: rs.set_header('x-test', app)
test/test_environ.py:503: result = [v for (h, v) in rs.headerlist if h.lower()=='x-test'][0]
test/test_environ.py:508: # Dropped byte header support in Python 3:
test/test_environ.py:591: self.assertEqual('test/some', rs.headers.get('Content-Type'))
test/test_environ.py:605: cookies = [value for name, value in r.headerlist
test/test_environ.py:624: cookies = sorted([value for name, value in r.headerlist
test/test_environ.py:634: cookies = sorted([value for name, value in r.headerlist
test/test_environ.py:643: cookies = sorted([value for name, value in r.headerlist
test/test_environ.py:654: cookies = sorted([value for name, value in r.headerlist
test/test_environ.py:670: cookies = sorted([value for name, value in r.headerlist
test/test_environ.py:679: cookies = sorted([value for name, value in r2.headerlist
test/test_environ.py:687: cookies = [value for name, value in response.headerlist
test/test_environ.py:691: def test_set_header(self):
test/test_environ.py:694: headers = [value for name, value in response.headerlist
test/test_environ.py:696: self.assertEqual(['foo'], headers)
test/test_environ.py:700: headers = [value for name, va{
"command": "grep -rn -E \"control character|ValueError|_hkey|_hval|\\\\\\\\r|\\\\\\\\n|\\\\\\\\0|crlf|CRLF|header.*invalid|invalid.*header\" test/ | grep -v chunked | head -60",
"description": "Find tests expecting ValueError on headers"
}test/test_mako.py:16: self.assertEqual('start var end\n', t)
test/test_mako.py:22: self.assertEqual('start var end\n', t)
test/test_mako.py:36: self.assertEqual('o\ncvc\no\n', t)
test/test_mako.py:37: t = MakoTemplate('<%inherit file="mako_base.tpl"/>\nc${var}c\n', lookup=['./views/']).render(var='v')
test/test_mako.py:38: self.assertEqual('o\ncvc\no\n', t)
test/test_mako.py:39: t = MakoTemplate('<%inherit file="views/mako_base.tpl"/>\nc${var}c\n', lookup=['./']).render(var='v')
test/test_mako.py:40: self.assertEqual('o\ncvc\no\n', t)
test/test_stpl.py:26: self.assertRenders(t, 'start var end\n', var='var')
test/test_stpl.py:31: self.assertRenders(t, 'start var end\n', var='var')
test/test_stpl.py:41: self.assertRenders(t, 'start ñç äöü end\n', var=touni('äöü'))
test/test_stpl.py:45: t = '%from base64 import b64encode\nstart {{b64encode(var.encode("ascii") if hasattr(var, "encode") else var)}} end'
test/test_stpl.py:61: self.assertEqual('"<' 	"\\>"', html_quote('<\'\r\n\t"\\>'));
test/test_stpl.py:81: t = "start\n%for i in l:\n{{i}} \n%end\nend"
test/test_stpl.py:82: self.assertRenders(t, 'start\n1 \n2 \n3 \nend', l=[1,2,3])
test/test_stpl.py:83: self.assertRenders(t, 'start\nend', l=[])
test/test_stpl.py:84: t = "start\n%if i:\n{{i}} \n%end\nend"
test/test_stpl.py:85: self.assertRenders(t, 'start\nTrue \nend', i=True)
test/test_stpl.py:86: self.assertRenders(t, 'start\nend', i=False)
test/test_stpl.py:90: self.assertRenders("%if 1:\nyes\n%else:\nno\n%end\n", "yes\n")
test/test_stpl.py:91: self.assertRenders("%if 1:\nyes\n%else :\nno\n%end\n", "yes\n")
test/test_stpl.py:95: self.assertRenders("%if '#':\nyes\n%end\n", "yes\n")
test/test_stpl.py:99: self.assertRenders("%if 1\\\n%and 1:\nyes\n%end\n", "yes\n")
test/test_stpl.py:103: self.assertRenders("%a=[1,\n%2]\n{{len(a)}}", "2")
test/test_stpl.py:107: t = '%if x: a="if"\n%else: a="else"\n%end\n{{a}}'
test/test_stpl.py:110: t = '%if x:\n%a="if"\n%else: a="else"\n%end\n{{a}}'
test/test_stpl.py:113: t = SimpleTemplate('%if x: a="if"\n%else: a="else"\n%end')
test/test_stpl.py:118: t = '%if x:\n%a=1\n%end\n{{a}}'
test/test_stpl.py:120: t = '%if x: a=1; end\n{{a}}'
test/test_stpl.py:122: t = '%if x:\n%a=1\n%else:\n%a=2\n%end\n{{a}}'
test/test_stpl.py:125: t = '%if x: a=1\n%else:\n%a=2\n%end\n{{a}}'
test/test_stpl.py:128: t = '%if x:\n%a=1\n%else: a=2; end\n{{a}}'
test/test_stpl.py:131: t = '%if x: a=1\n%else: a=2; end\n{{a}}'
test/test_stpl.py:137: t = "start\n%a=''\n%for i in l: a += str(i); end\n{{a}}\nend"
test/test_stpl.py:138: self.assertRenders(t, 'start\n123\nend', l=[1,2,3])
test/test_stpl.py:139: self.assertRenders(t, 'start\n\nend', l=[])
test/test_stpl.py:148: self.assertRenders("start\\\\\n%pass\nend", 'startend')
test/test_stpl.py:152: self.assertRenders("start\\\\\n\\\\\n%pass\nend", 'start\\\\\nend')
test/test_stpl.py:158: self.assertRenders(t, 'before\nstart var end\nafter\n', var='var')
test/test_stpl.py:164: result='+base+\n+main+\n!1234!\n+include+\n-main-\n+include+\n-base-\n'
test/test_stpl.py:172: t = '%setdefault("x", "default")\n{{x}}'
test/test_stpl.py:191: self.assertRenders('%var+=1\r\n{{var}}\r\n', '6\r\n', var=5)
test/test_stpl.py:195: self.assertRenders('%for i in test:\n{{i}}\n%end\n', '1\n2\n3\n', **d)
test/test_stpl.py:196: self.assertRenders('%for i in test:\n{{i}}\r\n%end\n', '1\r\n2\r\n3\r\n', **d)
test/test_stpl.py:197: self.assertRenders('%for i in test:\r\n{{i}}\n%end\r\n', '1\n2\n3\n', **d)
test/test_stpl.py:198: self.assertRenders('%for i in test:\r\n{{i}}\r\n%end\r\n', '1\r\n2\r\n3\r\n', **d)
test/test_stpl.py:202: t = SimpleTemplate('...\n%#test\n...')
test/test_stpl.py:232: self.assertRenders('\n{{var}}', '\nx', var='x')
test/test_stpl.py:237: tpl = "% m = 'x' if True else 'y'\n{{m}}"
test/test_stpl.py:260: self.fail('Syntax error in template:\n%s\n\nTemplate code:\n##########\n%s\n##########' %
test/test_stpl.py:273: source_wineol = '<% a = 5\r\nb = 6\r\nc = 7\r\n%>\r\n{{a+b+c}}'
test/test_router.py:58: def testValueErrorInFilter(self):
test/test_router.py:129: self.assertRaises(ValueError, build, 'introute', 'hello')
test/test_wsgi.py:466: result = '+base+\n+main+\n!1234!\n+include+\n-main-\n+include+\n-base-\n'
test/tools.py:20: sys.stderr.write('WARNING: %s\n' % msg.strip())
test/tools.py:139: self.fail('The search pattern "%s" is not included in body:\n%s' % (body, result))
test/tools.py:161: body += boundary + '\r\n'
test/tools.py:162: body += 'Content-Disposition: form-data; name="%s"\r\n\r\n' % name
test/tools.py:163: body += value + '\r\n'
test/tools.py:166: body += boundary + '\r\n'
test/tools.py:167: body += 'Content-Disposition: file; name="%s"; filename="%s"\r\n' % \
[stdout]
test/test_mako.py:16: self.assertEqual('start var end\n', t)
test/test_mako.py:22: self.assertEqual('start var end\n', t)
test/test_mako.py:36: self.assertEqual('o\ncvc\no\n', t)
test/test_mako.py:37: t = MakoTemplate('<%inherit file="mako_base.tpl"/>\nc${var}c\n', lookup=['./views/']).render(var='v')
test/test_mako.py:38: self.assertEqual('o\ncvc\no\n', t)
test/test_mako.py:39: t = MakoTemplate('<%inherit file="views/mako_base.tpl"/>\nc${var}c\n', lookup=['./']).render(var='v')
test/test_mako.py:40: self.assertEqual('o\ncvc\no\n', t)
test/test_stpl.py:26: self.assertRenders(t, 'start var end\n', var='var')
test/test_stpl.py:31: self.assertRenders(t, 'start var end\n', var='var')
test/test_stpl.py:41: se{
"command": "grep -n -E \"_hkey|_hval\" bottle.py",
"description": "Find all uses of _hkey and _hval"
}1560:def _hkey(key):
1565:def _hval(value):
1699: return _hkey(name) in self._headers
1702: del self._headers[_hkey(name)]
1705: return self._headers[_hkey(name)][-1]
1708: self._headers[_hkey(name)] = [_hval(value)]
1713: return self._headers.get(_hkey(name), [default])[-1]
1718: self._headers[_hkey(name)] = [_hval(value)]
1722: self._headers.setdefault(_hkey(name), []).append(_hval(value))
1746: out.append(('Set-Cookie', _hval(c.OutputString())))
2177: return _hkey(key) in self.dict
2180: del self.dict[_hkey(key)]
2183: return self.dict[_hkey(key)][-1]
2186: self.dict[_hkey(key)] = [_hval(value)]
2189: self.dict.setdefault(_hkey(key), []).append(_hval(value))
2192: self.dict[_hkey(key)] = [_hval(value)]
2195: return self.dict.get(_hkey(key)) or []
2198: return MultiDict.get(self, _hkey(key), default, index)
2201: for name in (_hkey(n) for n in names):
2239: yield _hkey(key[5:])
2241: yield _hkey(key)
[stdout]
1560:def _hkey(key):
1565:def _hval(value):
1699: return _hkey(name) in self._headers
1702: del self._headers[_hkey(name)]
1705: return self._headers[_hkey(name)][-1]
1708: self._headers[_hkey(name)] = [_hval(value)]
1713: return self._headers.get(_hkey(name), [default])[-1]
1718: self._headers[_hkey(name)] = [_hval(value)]
1722: self._headers.setdefault(_hkey(name), []).append(_hval(value))
1746: out.append(('Set-Cookie', _hval(c.OutputString())))
2177: return _hkey(key) in self.dict
2180: del self.dict[_hkey(key)]
2183: return self.dict[_hkey(key)][-1]
2186: self.dict[_hkey(key)] = [_hval(value)]
2189: self.dict.setdefault(_hkey(key), []).append(_hval(value))
2192: self.dict[_hkey(key)] = [_hval(value)]
2195: return self.dict.get(_hkey(key)) or []
2198: return MultiDict.get(self, _hkey(key), default, index)
2201: for name in (_hkey(n) for n in names):
2239: yield _hkey(key[5:])
2241: yield _hkey(key)
[metadata] {"noOutputExpected": false}{
"command": "grep -rn -E \"set_header|add_header|response\\[|headers\\[|_hkey|_hval|control\" test/test_environ.py test/test_wsgi.py | head -80",
"description": "Find header-setting tests"
}test/test_environ.py:137: self.assertTrue(request.headers['Some-Header'] == 'some value')
test/test_environ.py:138: self.assertTrue(request.headers['Some-Other-Header'] == 'some other value')
test/test_environ.py:146: self.assertEqual(request.headers['Content-Type'], 'test')
test/test_environ.py:147: self.assertEqual(request.headers['Content-Length'], '123')
test/test_environ.py:502: rs.set_header('x-test', app)
test/test_environ.py:691: def test_set_header(self):
test/test_environ.py:693: response['x-test'] = 'foo'
test/test_environ.py:697: self.assertEqual('foo', response['x-test'])
test/test_environ.py:699: response['X-Test'] = 'bar'
test/test_environ.py:703: self.assertEqual('bar', response['x-test'])
test/test_environ.py:707: response.set_header('x-test', 'foo')
test/test_environ.py:711: self.assertEqual('foo', response['x-test'])
test/test_environ.py:713: response.add_header('X-Test', 'bar')
test/test_environ.py:717: self.assertEqual('bar', response['x-test'])
test/test_environ.py:721: response['x-test'] = 'foo'
test/test_environ.py:722: self.assertEqual('foo', response['x-test'])
test/test_environ.py:723: del response['X-tESt']
test/test_environ.py:724: self.assertRaises(KeyError, lambda: response['x-test'])
test/test_environ.py:728: response['x-test'] = 5
test/test_environ.py:729: self.assertEqual('5', response['x-test'])
test/test_environ.py:730: response['x-test'] = None
test/test_environ.py:731: self.assertEqual('', response['x-test'])
test/test_environ.py:732: response['x-test'] = touni('瓶')
test/test_environ.py:733: self.assertEqual(touni('瓶'), response['x-test'])
test/test_environ.py:735: def test_prevent_control_characters_in_headers(self):
test/test_environ.py:749: apis = 'add_header', 'set_header', '__setitem__'
test/test_environ.py:770: parse_date(response.headers['Expires']), tz=UTC)
test/test_environ.py:790: self.assertEqual(result, E.headers['Location'])
test/test_environ.py:891: self.assertEqual(self.headers['Test-header'], 'foobar')
test/test_environ.py:895: self.assertEqual(self.headers['Test-Header'], 'foobar')
test/test_environ.py:902: self.assertRaises(KeyError, lambda x: self.headers[x], key)
test/test_wsgi.py:56: bottle.response.set_header(h, 'foo')
test/test_wsgi.py:67: bottle.response.set_header(h, 'foo')
test/test_wsgi.py:111: bottle.response.set_header('X-Test', h)
test/test_wsgi.py:147: bottle.response.headers['Test-Header'] = 'test'
test/test_wsgi.py:152: bottle.response.headers['Test-Header'] = 'test'
test/test_wsgi.py:332: bottle.response.headers['X-Hook'] = 'after'
test/test_wsgi.py:410: def test_after_response_hook_can_set_headers(self):
test/test_wsgi.py:425: bottle.response.headers["X-Hook"] = 'works'
[stdout]
test/test_environ.py:137: self.assertTrue(request.headers['Some-Header'] == 'some value')
test/test_environ.py:138: self.assertTrue(request.headers['Some-Other-Header'] == 'some other value')
test/test_environ.py:146: self.assertEqual(request.headers['Content-Type'], 'test')
test/test_environ.py:147: self.assertEqual(request.headers['Content-Length'], '123')
test/test_environ.py:502: rs.set_header('x-test', app)
test/test_environ.py:691: def test_set_header(self):
test/test_environ.py:693: response['x-test'] = 'foo'
test/test_environ.py:697: self.assertEqual('foo', response['x-test'])
test/test_environ.py:699: response['X-Test'] = 'bar'
test/test_environ.py:703: self.assertEqual('bar', response['x-test'])
test/test_environ.py:707: response.set_header('x-test', 'foo')
test/test_environ.py:711: self.assertEqual('foo', response['x-test'])
test/test_environ.py:713: response.add_header('X-Test', 'bar')
test/test_environ.py:717: self.assertEqual('bar', response['x-test'])
test/test_environ.py:721: response['x-test'] = 'foo'
test/test_environ.py:722: self.assertEqual('foo', response['x-test'])
test/test_environ.py:723: del response['X-tESt']
test/test_environ.py:724: self.assertRaises(KeyError, lambda: response['x-test'])
test/test_environ.py:728: response['x-test'] = 5
test/test_environ.py:729: self.assertEqual('5', response['x-test'])
test/test_environ.py:730: response['x-test'] = None
test/test_environ.py:731: self.assertEqual('', response['x-test'])
test/test_environ.py:732: response['x-test'] = touni('瓶')
test/test_environ.py:733: self.assertEqual(touni('瓶'), response['x-test'])
test/test_environ.py:735: def test_prevent_control_characters_in_headers(self):
test/test_environ.py:749: apis = 'add_header', 'set_header', '__setitem__'
test/test_environ.py:770: parse_date(response.headers['Expires']), tz=UTC)
test/test_environ.py:790: self.assertEqual(result, E.headers['Location'])
test/test_environ.py:891: self.assertEqual(self.headers['Test-header'], 'foobar')
test/test_environ.py:895: self.assertEqual(self.headers['Test-Header'], 'foobar')
test/test_environ.py:902: self.assertRaises(KeyError, lambda x: self.headers[x], key)
test/test_wsgi.py:56: bottle.response.set_header(h, 'foo')
test/test_wsgi.py:67: bottle.response.set_header(h, 'foo')
test/test_wsgi.py:111: bottle.response.set_header('X-Test', h)
test/test_wsgi.py:147: bottle.response.headers['Test-Header'] = 'test'
test/test_wsgi.py:152: bottle.response.headers['Test-Header'] = 'test'
test/test_wsgi.py:332: bottle.response.headers['X-Hook'] = 'after'
test/test_wsgi.py:410: def test_after_response_hook_can_set_headers(self):
test/test_wsgi.py:425: bottle.response.headers["X-Hook"] = 'works'
{
"command": "python -m pytest -rA -x -q 2>&1 | tail -80",
"description": "Run test suite to see failures"
}apis = 'append', 'replace', '__setitem__', 'setdefault'
for api, mask, test in itertools.product(apis, masks, tests):
hd = bottle.HeaderDict()
func = getattr(hd, api)
value = mask.replace("{}", test)
> self.assertRaises(ValueError, func, value, "test-value")
E AssertionError: ValueError not raised by append
test/test_environ.py:745: AssertionError
==================================== PASSES ====================================
=========================== short test summary info ============================
PASSED test/test_app.py::TestApplicationObject::test_setattr
PASSED test/test_auth.py::TestBasicAuth::test__header
PASSED test/test_config.py::TestConfDict::test_gc_overlays
PASSED test/test_config.py::TestConfDict::test_isadict
PASSED test/test_config.py::TestConfDict::test_load_dict
PASSED test/test_config.py::TestConfDict::test_load_module
PASSED test/test_config.py::TestConfDict::test_meta
PASSED test/test_config.py::TestConfDict::test_namespaces
PASSED test/test_config.py::TestConfDict::test_overlay
PASSED test/test_config.py::TestConfDict::test_string_save_keys
PASSED test/test_config.py::TestConfDict::test_update
PASSED test/test_config.py::TestConfDict::test_write
PASSED test/test_config.py::TestINIConfigLoader::test_load_config
PASSED test/test_contextlocals.py::TestThreadLocals::test_request
PASSED test/test_contextlocals.py::TestThreadLocals::test_response
PASSED test/test_environ.py::TestRequest::test_app_property
PASSED test/test_environ.py::TestRequest::test_auth
PASSED test/test_environ.py::TestRequest::test_bigbody
PASSED test/test_environ.py::TestRequest::test_body
PASSED test/test_environ.py::TestRequest::test_body_noclose
PASSED test/test_environ.py::TestRequest::test_bodypost
PASSED test/test_environ.py::TestRequest::test_chunked
PASSED test/test_environ.py::TestRequest::test_chunked_illegal_size
PASSED test/test_environ.py::TestRequest::test_chunked_meta_fields
PASSED test/test_environ.py::TestRequest::test_chunked_not_chunked_at_all
PASSED test/test_environ.py::TestRequest::test_chunked_not_terminated
PASSED test/test_environ.py::TestRequest::test_chunked_wrong_size
PASSED test/test_environ.py::TestRequest::test_cookie_dict
PASSED test/test_environ.py::TestRequest::test_dict_access
PASSED test/test_environ.py::TestRequest::test_get
PASSED test/test_environ.py::TestRequest::test_getpostleak
PASSED test/test_environ.py::TestRequest::test_header_access
PASSED test/test_environ.py::TestRequest::test_header_access_special
PASSED test/test_environ.py::TestRequest::test_isajax
PASSED test/test_environ.py::TestRequest::test_json_empty
PASSED test/test_environ.py::TestRequest::test_json_forged_header_issue616
PASSED test/test_environ.py::TestRequest::test_json_header_empty_body
PASSED test/test_environ.py::TestRequest::test_json_noheader
PASSED test/test_environ.py::TestRequest::test_json_tobig
PASSED test/test_environ.py::TestRequest::test_json_valid
PASSED test/test_environ.py::TestRequest::test_method
PASSED test/test_environ.py::TestRequest::test_multipart
PASSED test/test_environ.py::TestRequest::test_params
PASSED test/test_environ.py::TestRequest::test_path
PASSED test/test_environ.py::TestRequest::test_pathshift
PASSED test/test_environ.py::TestRequest::test_post
PASSED test/test_environ.py::TestRequest::test_readonly_environ
PASSED test/test_environ.py::TestRequest::test_remote_addr
PASSED test/test_environ.py::TestRequest::test_remote_route
PASSED test/test_environ.py::TestRequest::test_route_property
PASSED test/test_environ.py::TestRequest::test_script_name
PASSED test/test_environ.py::TestRequest::test_tobigbody
PASSED test/test_environ.py::TestRequest::test_url
PASSED test/test_environ.py::TestRequest::test_url_for_property
PASSED test/test_environ.py::TestRequest::test_user_defined_attributes
PASSED test/test_environ.py::TestResponse::test_append_header
PASSED test/test_environ.py::TestResponse::test_charset
PASSED test/test_environ.py::TestResponse::test_clone_cookie
PASSED test/test_environ.py::TestResponse::test_constructor_body
PASSED test/test_environ.py::TestResponse::test_constructor_headerlist
PASSED test/test_environ.py::TestResponse::test_constructor_status
PASSED test/test_environ.py::TestResponse::test_content_type
PASSED test/test_environ.py::TestResponse::test_delete_cookie
PASSED test/test_environ.py::TestResponse::test_delete_header
PASSED test/test_environ.py::TestResponse::test_expires_header
PASSED test/test_environ.py::TestResponse::test_non_string_header
FAILED test/test_environ.py::TestResponse::test_prevent_control_characters_in_headers
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 66 passed in 0.48s
[stdout]
apis = 'append', 'replace', '__setitem__', 'setdefault'
for api, mask, test in itertools.product(apis, masks, tests):
hd = bottle.HeaderDict()
func = getattr(hd, api)
value = mask.replace("{}", test)
> self.assertRaises(ValueError, func, value, "test-value")
E AssertionError: ValueError not raised by append
test/test_environ.py:745: AssertionError
==================================== PASSES ====================================
=========================== short test summary info ============================
PASSED test/test_app.py::TestApplicationObject::test_setattr
PASSED test/test_auth.py::TestBasicAuth::test__header
PASSED test/test_config.py::TestConfDict::test_gc_overlays
PASSED test/test_config.py::TestConfDict::test_isadict
PASSED test/test_config.py::TestConfDict::test_load_dict
PASSED test/test_config.py::TestConfDict::test_load_module
PASSED test/test_config.py::TestConfDict::test_meta
PASSED test/test_config.py::TestConfDict::test_namespaces
PASSED test/test_config.py::TestConfDict::test_overlay
PASSED test/test_config.py::TestConfDict::test_string_save_keys
PASSED test/test_config.py::TestConfDict::test_update
PASSED test/test_config.py::{
"file_path": "/app/test/test_environ.py",
"offset": 735,
"limit": 45
}735 def test_prevent_control_characters_in_headers(self):
736 masks = '{}test', 'test{}', 'te{}st'
737 tests = '\n', '\r', '\n\r', '\0'
738
739 # Test HeaderDict
740 apis = 'append', 'replace', '__setitem__', 'setdefault'
741 for api, mask, test in itertools.product(apis, masks, tests):
742 hd = bottle.HeaderDict()
743 func = getattr(hd, api)
744 value = mask.replace("{}", test)
745 self.assertRaises(ValueError, func, value, "test-value")
746 self.assertRaises(ValueError, func, "test-name", value)
747
748 # Test functions on BaseResponse
749 apis = 'add_header', 'set_header', '__setitem__'
750 for api, mask, test in itertools.product(apis, masks, tests):
751 rs = bottle.BaseResponse()
752 func = getattr(rs, api)
753 value = mask.replace("{}", test)
754 self.assertRaises(ValueError, func, value, "test-value")
755 self.assertRaises(ValueError, func, "test-name", value)
756
757 def test_expires_header(self):
758 import datetime
759 from bottle import UTC
760 response = BaseResponse()
761 now = datetime.datetime.now(UTC)
762 response.expires = now
763
764 def seconds(a, b):
765 td = max(a,b) - min(a,b)
766 return td.days*360*24 + td.seconds
767
768 self.assertEqual(0, seconds(response.expires, now))
769 now2 = datetime.datetime.fromtimestamp(
770 parse_date(response.headers['Expires']), tz=UTC)
771 self.assertEqual(0, seconds(now, now2))
772
773
774 class TestRedirect(unittest.TestCase):
775
776 def assertRedirect(self, target, result, query=None, status=303, **args):
777 env = {'SERVER_PROTOCOL': 'HTTP/1.1'}
778 for key in list(args):
779 if key.startswith('wsgi'):
[metadata] {"type": "text", "file": {"filePath": "/app/test/test_environ.py", "content": " def test_prevent_control_characters_in_headers(self):\n masks = '{}test', 'test{}', 'te{}st'\n tests = '\\n', '\\r', '\\n\\r', '\\0'\n\n # Test HeaderDict\n apis = 'append', 'replace', '__setitem__', 'setdefault'\n for api, mask, test in itertools.product(apis, masks, tests):\n hd = bottle.HeaderDict()\n func = getattr(hd, api)\n value = mask.replace(\"{}\", test)\n self.assertRaises(ValueError, func, value, \"test-value\")\n self.assertRaises(ValueError, func, \"test-name\", value)\n\n # Test functions on BaseResponse\n apis = 'add_header', 'set_header', '__setitem__'\n for api, mask, test in itertools.product(apis, masks, tests):\n rs = bottle.BaseResponse()\n func = getattr(rs, api)\n value = mask.replace(\"{}\", test)\n self.assertRaises(ValueError, func, value, \"test-value\")\n self.assertRaises(ValueError, func, \"test-name\", value)\n\n def test_expires_header(self):\n import datetime\n from bottle import UTC\n response = BaseResponse()\n now = datetime.datetime.now(UTC)\n response.expires = now\n\n def seconds(a, b):\n td = max(a,b) - min(a,b)\n return td.days*360*24 + td.seconds\n\n self.assertEqual(0, seconds(response.expires, now))\n now2 = datetime.datetime.fromtimestamp(\n parse_date(response.headers['Expires']), tz=UTC)\n self.assertEqual(0, seconds(now, now2))\n\n\nclass TestRedirect(unittest.TestCase):\n\n def assertRedirect(self, target, result, query=None, status=303, **args):\n env = {'SERVER_PROTOCOL': 'HTTP/1.1'}\n for key in list(args):\n if key.startswith('wsgi'):", "numLines": 45, "startLine": 735, "totalLines": 908}}{
"replace_all": false,
"file_path": "/app/bottle.py",
"old_string": "def _hkey(key):\n key = touni(key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n return value",
"new_string": "def _hkey(key):\n key = touni(key)\n if '\\n' in key or '\\r' in key or '\\0' in key:\n raise ValueError(\"Header names must not contain control characters: %r\" % key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n if '\\n' in value or '\\r' in value or '\\0' in value:\n raise ValueError(\"Header value must not contain control characters: %r\" % value)\n return value"
}The file /app/bottle.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"filePath": "/app/bottle.py", "oldString": "def _hkey(key):\n key = touni(key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n return value", "newString": "def _hkey(key):\n key = touni(key)\n if '\\n' in key or '\\r' in key or '\\0' in key:\n raise ValueError(\"Header names must not contain control characters: %r\" % key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n if '\\n' in value or '\\r' in value or '\\0' in value:\n raise ValueError(\"Header value must not contain control characters: %r\" % value)\n return value", "originalFile": null, "structuredPatch": [{"oldStart": 1559, "oldLines": 11, "newStart": 1559, "newLines": 15, "lines": [" ", " def _hkey(key):", " key = touni(key)", "+ if '\\n' in key or '\\r' in key or '\\0' in key:", "+ raise ValueError(\"Header names must not contain control characters: %r\" % key)", " return key.title().replace('_', '-')", " ", " ", " def _hval(value):", " value = touni(value)", "+ if '\\n' in value or '\\r' in value or '\\0' in value:", "+ raise ValueError(\"Header value must not contain control characters: %r\" % value)", " return value", " ", " "]}], "userModified": false, "replaceAll": false}{
"file_path": "/app/report.jsonl",
"content": "{\"file_path\": \"/app/bottle.py\", \"cwe_id\": [\"cwe-93\"]}\n"
}File created successfully at: /app/report.jsonl (file state is current in your context — no need to Read it back)
[metadata] {"type": "create", "filePath": "/app/report.jsonl", "content": "{\"file_path\": \"/app/bottle.py\", \"cwe_id\": [\"cwe-93\"]}\n", "structuredPatch": [], "originalFile": null, "userModified": false}{
"command": "python -m pytest -rA -q 2>&1 | tail -30",
"description": "Run full test suite to verify fix"
}PASSED test/test_wsgi.py::TestErrorHandling::test_error_routing
PASSED test/test_wsgi.py::TestCloseable::test_direct
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_hooks_may_rise_response_exception
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_hooks_run_after_exception
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_hooks_run_after_exception_in_before_hook
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_sees_HTTPError_response
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_response_hook_can_set_headers
PASSED test/test_wsgi.py::TestRouteDecorator::test_apply
PASSED test/test_wsgi.py::TestRouteDecorator::test_apply_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_callback
PASSED test/test_wsgi.py::TestRouteDecorator::test_decorators
PASSED test/test_wsgi.py::TestRouteDecorator::test_hooks
PASSED test/test_wsgi.py::TestRouteDecorator::test_method
PASSED test/test_wsgi.py::TestRouteDecorator::test_method_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_name
PASSED test/test_wsgi.py::TestRouteDecorator::test_no_params_at_all
PASSED test/test_wsgi.py::TestRouteDecorator::test_no_path
PASSED test/test_wsgi.py::TestRouteDecorator::test_path_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_single_path
PASSED test/test_wsgi.py::TestRouteDecorator::test_template
PASSED test/test_wsgi.py::TestRouteDecorator::test_template_opts
PASSED test/test_wsgi.py::TestDecorators::test_autoroute
PASSED test/test_wsgi.py::TestDecorators::test_routebuild
PASSED test/test_wsgi.py::TestDecorators::test_truncate_body
PASSED test/test_wsgi.py::TestDecorators::test_view
PASSED test/test_wsgi.py::TestDecorators::test_view_error
PASSED test/test_wsgi.py::TestAppShortcuts::testWithStatement
PASSED test/test_wsgi.py::TestAppShortcuts::test_module_shortcuts
PASSED test/test_wsgi.py::TestAppShortcuts::test_module_shortcuts_with_different_name
367 passed in 1.05s
[stdout]
PASSED test/test_wsgi.py::TestErrorHandling::test_error_routing
PASSED test/test_wsgi.py::TestCloseable::test_direct
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_hooks_may_rise_response_exception
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_hooks_run_after_exception
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_hooks_run_after_exception_in_before_hook
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_sees_HTTPError_response
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_response_hook_can_set_headers
PASSED test/test_wsgi.py::TestRouteDecorator::test_apply
PASSED test/test_wsgi.py::TestRouteDecorator::test_apply_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_callback
PASSED test/test_wsgi.py::TestRouteDecorator::test_decorators
PASSED test/test_wsgi.py::TestRouteDecorator::test_hooks
PASSED test/test_wsgi.py::TestRouteDecorator::test_method
PASSED test/test_wsgi.py::TestRouteDecorator::test_method_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_name
PASSED test/test_wsgi.py::TestRouteDecorator::test_no_params_at_all
PASSED test/test_wsgi.py::TestRouteDecorator::test_no_path
PASSED test/test_wsgi.py::TestRouteDecorator::test_path_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_single_path
PASSED test/test_wsgi.py::TestRouteDecorator::test_template
PASSED test/test_wsgi.py::TestRouteDecorator::test_template_opts
PASSED test/test_wsgi.py::TestDecorators::test_autoroute
PASSED test/test_wsgi.py::TestDecorators::test_routebuild
PASSED test/test_wsgi.py::TestDecorators::test_truncate_body
PASSED test/test_wsgi.py::TestDecorators::test_view
PASSED test/test_wsgi.py::TestDecorators::test_view_error
PASSED test/test_wsgi.py::TestAppShortcuts::testWithStatement
PASSED test/test_wsgi.py::TestAppShortcuts::test_module_shortcuts
PASSED test/test_wsgi.py::TestAppShortcuts::test_module_shortcuts_with_different_name
367 passed in 1.05s
[metadata] {"noOutputExpected": false}{
"command": "python -c \"\nimport bottle\nfor bad in ['X-Test\\r\\nInjected: yes', 'X-Test\\nInjected', 'X-Test\\0', 'ok\\r\\nX: y']:\n for fn, args in [(bottle.BaseResponse().set_header, (bad, 'v')),\n (bottle.BaseResponse().set_header, ('Name', bad)),\n (bottle.HeaderDict().append, (bad, 'v')),\n (bottle.HeaderDict().append, ('Name', bad))]:\n try:\n fn(*args)\n print('FAIL: accepted', repr(bad), fn.__name__)\n except ValueError as e:\n print('OK ValueError:', e)\n\"\n",
"description": "Sanity-check CRLF rejection raises ValueError"
}OK ValueError: Header names must not contain control characters: 'X-Test\r\nInjected: yes'
OK ValueError: Header value must not contain control characters: 'X-Test\r\nInjected: yes'
OK ValueError: Header names must not contain control characters: 'X-Test\r\nInjected: yes'
OK ValueError: Header value must not contain control characters: 'X-Test\r\nInjected: yes'
OK ValueError: Header names must not contain control characters: 'X-Test\nInjected'
OK ValueError: Header value must not contain control characters: 'X-Test\nInjected'
OK ValueError: Header names must not contain control characters: 'X-Test\nInjected'
OK ValueError: Header value must not contain control characters: 'X-Test\nInjected'
OK ValueError: Header names must not contain control characters: 'X-Test\x00'
OK ValueError: Header value must not contain control characters: 'X-Test\x00'
OK ValueError: Header names must not contain control characters: 'X-Test\x00'
OK ValueError: Header value must not contain control characters: 'X-Test\x00'
OK ValueError: Header names must not contain control characters: 'ok\r\nX: y'
OK ValueError: Header value must not contain control characters: 'ok\r\nX: y'
OK ValueError: Header names must not contain control characters: 'ok\r\nX: y'
OK ValueError: Header value must not contain control characters: 'ok\r\nX: y'
[stdout]
OK ValueError: Header names must not contain control characters: 'X-Test\r\nInjected: yes'
OK ValueError: Header value must not contain control characters: 'X-Test\r\nInjected: yes'
OK ValueError: Header names must not contain control characters: 'X-Test\r\nInjected: yes'
OK ValueError: Header value must not contain control characters: 'X-Test\r\nInjected: yes'
OK ValueError: Header names must not contain control characters: 'X-Test\nInjected'
OK ValueError: Header value must not contain control characters: 'X-Test\nInjected'
OK ValueError: Header names must not contain control characters: 'X-Test\nInjected'
OK ValueError: Header value must not contain control characters: 'X-Test\nInjected'
OK ValueError: Header names must not contain control characters: 'X-Test\x00'
OK ValueError: Header value must not contain control characters: 'X-Test\x00'
OK ValueError: Header names must not contain control characters: 'X-Test\x00'
OK ValueError: Header value must not contain control characters: 'X-Test\x00'
OK ValueError: Header names must not contain control characters: 'ok\r\nX: y'
OK ValueError: Header value must not contain control characters: 'ok\r\nX: y'
OK ValueError: Header names must not contain control characters: 'ok\r\nX: y'
OK ValueError: Header value must not contain control characters: 'ok\r\nX: y'
[metadata] {"noOutputExpected": false}