mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
Check Content-Length header.
For not chunked request do validation Content-Length header and return 400 if invalid.
This commit is contained in:
parent
238f252a3a
commit
4be3282440
@ -35,18 +35,19 @@ class InvalidHTTPVersion(ParseException):
|
||||
return "Invalid HTTP Version: %s" % self.version
|
||||
|
||||
class InvalidHeader(ParseException):
|
||||
def __init__(self, hdr):
|
||||
def __init__(self, hdr, req=None):
|
||||
self.hdr = hdr
|
||||
self.req = req
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid HTTP Header: %r" % self.hdr
|
||||
return "Invalid HTTP Header: %s" % self.hdr
|
||||
|
||||
class InvalidHeaderName(ParseException):
|
||||
def __init__(self, hdr):
|
||||
self.hdr = hdr
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid HTTP header name: %r" % self.hdr
|
||||
return "Invalid HTTP header name: %s" % self.hdr
|
||||
|
||||
class InvalidChunkSize(ParseException):
|
||||
def __init__(self, data):
|
||||
|
||||
@ -94,25 +94,27 @@ class Message(object):
|
||||
|
||||
def set_body_reader(self):
|
||||
chunked = False
|
||||
response_length = None
|
||||
content_length = None
|
||||
for (name, value) in self.headers:
|
||||
if name == "CONTENT-LENGTH":
|
||||
try:
|
||||
response_length = int(value)
|
||||
except ValueError:
|
||||
response_length = None
|
||||
content_length = value
|
||||
elif name == "TRANSFER-ENCODING":
|
||||
chunked = value.lower() == "chunked"
|
||||
elif name == "SEC-WEBSOCKET-KEY1":
|
||||
response_length = 8
|
||||
|
||||
if response_length is not None or chunked:
|
||||
break
|
||||
content_length = 8
|
||||
|
||||
if chunked:
|
||||
self.body = Body(ChunkedReader(self, self.unreader))
|
||||
elif response_length is not None:
|
||||
self.body = Body(LengthReader(self.unreader, response_length))
|
||||
elif content_length is not None:
|
||||
try:
|
||||
content_length = int(content_length)
|
||||
except ValueError:
|
||||
raise InvalidHeader("CONTENT-LENGTH", req=self)
|
||||
|
||||
if content_length < 0:
|
||||
raise InvalidHeader("CONTENT-LENGTH", req=self)
|
||||
|
||||
self.body = Body(LengthReader(self.unreader, content_length))
|
||||
else:
|
||||
self.body = Body(EOFReader(self.unreader))
|
||||
|
||||
|
||||
@ -142,7 +142,9 @@ class Worker(object):
|
||||
elif isinstance(exc, InvalidHTTPVersion):
|
||||
mesg = "<p>Invalid HTTP Version '%s'</p>" % str(exc)
|
||||
elif isinstance(exc, (InvalidHeaderName, InvalidHeader,)):
|
||||
mesg = "<p>Invalid Header '%s'</p>" % str(exc)
|
||||
mesg = "<p>%s</p>" % str(exc)
|
||||
if not req and hasattr(exc, "req"):
|
||||
req = exc.req # for access log
|
||||
elif isinstance(exc, LimitRequestLine):
|
||||
mesg = "<p>%s</p>" % str(exc)
|
||||
elif isinstance(exc, LimitRequestHeaders):
|
||||
|
||||
4
tests/requests/invalid/014.http
Normal file
4
tests/requests/invalid/014.http
Normal file
@ -0,0 +1,4 @@
|
||||
PUT /stuff/here?foo=bar HTTP/1.0\r\n
|
||||
CONTENT-LENGTH: -1\r\n
|
||||
\r\n
|
||||
{"test": "-1}
|
||||
3
tests/requests/invalid/014.py
Normal file
3
tests/requests/invalid/014.py
Normal file
@ -0,0 +1,3 @@
|
||||
from gunicorn.http.errors import InvalidHeader
|
||||
|
||||
request = InvalidHeader
|
||||
4
tests/requests/invalid/015.http
Normal file
4
tests/requests/invalid/015.http
Normal file
@ -0,0 +1,4 @@
|
||||
POST /stuff/here?foo=bar HTTP/1.0\r\n
|
||||
CONTENT-LENGTH: bla-bla-bla\r\n
|
||||
\r\n
|
||||
{"test": "-1}
|
||||
3
tests/requests/invalid/015.py
Normal file
3
tests/requests/invalid/015.py
Normal file
@ -0,0 +1,3 @@
|
||||
from gunicorn.http.errors import InvalidHeader
|
||||
|
||||
request = InvalidHeader
|
||||
19
tests/requests/valid/025.http
Normal file
19
tests/requests/valid/025.http
Normal file
@ -0,0 +1,19 @@
|
||||
POST /chunked_cont_h_at_first HTTP/1.1\r\n
|
||||
Content-Length: -1\r\n
|
||||
Transfer-Encoding: chunked\r\n
|
||||
\r\n
|
||||
5; some; parameters=stuff\r\n
|
||||
hello\r\n
|
||||
6; blahblah; blah\r\n
|
||||
world\r\n
|
||||
0\r\n
|
||||
\r\n
|
||||
PUT /chunked_cont_h_at_last HTTP/1.1\r\n
|
||||
Transfer-Encoding: chunked\r\n
|
||||
Content-Length: -1\r\n
|
||||
\r\n
|
||||
5; some; parameters=stuff\r\n
|
||||
hello\r\n
|
||||
6; blahblah; blah\r\n
|
||||
world\r\n
|
||||
0\r\n
|
||||
23
tests/requests/valid/025.py
Normal file
23
tests/requests/valid/025.py
Normal file
@ -0,0 +1,23 @@
|
||||
req1 = {
|
||||
"method": "POST",
|
||||
"uri": uri("/chunked_cont_h_at_first"),
|
||||
"version": (1, 1),
|
||||
"headers": [
|
||||
("CONTENT-LENGTH", "-1"),
|
||||
("TRANSFER-ENCODING", "chunked")
|
||||
],
|
||||
"body": "hello world"
|
||||
}
|
||||
|
||||
req2 = {
|
||||
"method": "PUT",
|
||||
"uri": uri("/chunked_cont_h_at_last"),
|
||||
"version": (1, 1),
|
||||
"headers": [
|
||||
("TRANSFER-ENCODING", "chunked"),
|
||||
("CONTENT-LENGTH", "-1"),
|
||||
],
|
||||
"body": "hello world"
|
||||
}
|
||||
|
||||
request = [req1, req2]
|
||||
Loading…
x
Reference in New Issue
Block a user