Handle multiple transfer-encoding

This commit is contained in:
Emile Fugulin 2019-11-18 22:29:02 -05:00
parent bd8670b4db
commit f74324bd75
9 changed files with 74 additions and 3 deletions

View File

@ -118,3 +118,11 @@ class ForbiddenProxyRequest(ParseException):
class InvalidSchemeHeaders(ParseException):
def __str__(self):
return "Contradictory scheme headers"
class UnsupportedTransferEncoding(ParseException):
def __init__(self, te):
self.te = te
def __str__(self):
return "Unsupported Transfer-Encoding: %s" % self.te

View File

@ -12,7 +12,7 @@ from gunicorn.http.unreader import SocketUnreader
from gunicorn.http.body import ChunkedReader, LengthReader, EOFReader, Body
from gunicorn.http.errors import (InvalidHeader, InvalidHeaderName, NoMoreData,
InvalidRequestLine, InvalidRequestMethod, InvalidHTTPVersion,
LimitRequestLine, LimitRequestHeaders)
LimitRequestLine, LimitRequestHeaders, UnsupportedTransferEncoding)
from gunicorn.http.errors import InvalidProxyLine, ForbiddenProxyRequest
from gunicorn.http.errors import InvalidSchemeHeaders
from gunicorn.util import bytes_to_str, split_request_uri
@ -135,7 +135,13 @@ class Message(object):
raise InvalidHeader("CONTENT-LENGTH", req=self)
content_length = value
elif name == "TRANSFER-ENCODING":
chunked = value.lower() == "chunked"
normalized_value = value.lower()
if normalized_value == "identity":
pass
elif normalized_value == "chunked":
chunked = True
else:
raise UnsupportedTransferEncoding(normalized_value)
elif name == "SEC-WEBSOCKET-KEY1":
content_length = 8

View File

@ -20,6 +20,7 @@ from gunicorn.http.errors import (
InvalidProxyLine, InvalidRequestLine,
InvalidRequestMethod, InvalidSchemeHeaders,
LimitRequestHeaders, LimitRequestLine,
UnsupportedTransferEncoding
)
from gunicorn.http.wsgi import Response, default_environ
from gunicorn.reloader import reloader_engines
@ -206,7 +207,7 @@ class Worker(object):
LimitRequestLine, LimitRequestHeaders,
InvalidProxyLine, ForbiddenProxyRequest,
InvalidSchemeHeaders,
SSLError)):
SSLError, UnsupportedTransferEncoding)):
status_int = 400
reason = "Bad Request"
@ -237,6 +238,10 @@ class Worker(object):
reason = "Forbidden"
mesg = "'%s'" % str(exc)
status_int = 403
elif isinstance(exc, UnsupportedTransferEncoding):
reason = "Not implemented"
mesg = "'%s'" % str(exc)
status_int = 501
msg = "Invalid request from ip={ip}: {error}"
self.log.debug(msg.format(ip=addr[0], error=str(exc)))

View File

@ -0,0 +1,5 @@
GET /stuff/here?foo=bar HTTP/1.1\r\n
Transfer-Encoding: chunked\r\n
Transfer-Encoding: compress\r\n
\r\n
xyz

View File

@ -0,0 +1,5 @@
from gunicorn.config import Config
from gunicorn.http.errors import UnsupportedTransferEncoding
cfg = Config()
request = UnsupportedTransferEncoding

View File

@ -0,0 +1,7 @@
GET /stuff/here?foo=bar HTTP/1.1\r\n
Transfer-Encoding: chunked\r\n
Transfer-Encoding: identity\r\n
\r\n
5\r\n
hello\r\n
000\r\n

View File

@ -0,0 +1,14 @@
from gunicorn.config import Config
cfg = Config()
request = {
"method": "GET",
"uri": uri("/stuff/here?foo=bar"),
"version": (1, 1),
"headers": [
('TRANSFER-ENCODING', 'chunked'),
('TRANSFER-ENCODING', 'identity')
],
"body": b"hello"
}

View File

@ -0,0 +1,7 @@
GET /stuff/here?foo=bar HTTP/1.1\r\n
Transfer-Encoding: identity\r\n
Transfer-Encoding: chunked\r\n
\r\n
5\r\n
hello\r\n
000\r\n

View File

@ -0,0 +1,14 @@
from gunicorn.config import Config
cfg = Config()
request = {
"method": "GET",
"uri": uri("/stuff/here?foo=bar"),
"version": (1, 1),
"headers": [
('TRANSFER-ENCODING', 'identity'),
('TRANSFER-ENCODING', 'chunked')
],
"body": b"hello"
}