mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
improve content-length handling. Chunked encoding is only used when not
content-length is provided and http version >= 1.1. In other case send until we content is empty. Also HTTP don't expect we can send more than content-length if header is set, so discard any content if we have already send the expected lenghth. (spotted by @GrahamDumpleton) reviewed and OK by @davisp. More readable function by @davisp
This commit is contained in:
parent
cd726f6d8c
commit
39f5d313f7
@ -117,6 +117,9 @@ class Response(object):
|
|||||||
self.should_close = req.should_close()
|
self.should_close = req.should_close()
|
||||||
self.headers = []
|
self.headers = []
|
||||||
self.headers_sent = False
|
self.headers_sent = False
|
||||||
|
self.clength = -1
|
||||||
|
#self.te = None
|
||||||
|
self.sent = 0
|
||||||
|
|
||||||
def force_close(self):
|
def force_close(self):
|
||||||
self.should_close = True
|
self.should_close = True
|
||||||
@ -133,17 +136,19 @@ class Response(object):
|
|||||||
|
|
||||||
self.status = status
|
self.status = status
|
||||||
self.process_headers(headers)
|
self.process_headers(headers)
|
||||||
|
self.chunked = self.is_chunked()
|
||||||
return self.write
|
return self.write
|
||||||
|
|
||||||
def process_headers(self, headers):
|
def process_headers(self, headers):
|
||||||
for name, value in headers:
|
for name, value in headers:
|
||||||
assert isinstance(name, basestring), "%r is not a string" % name
|
assert isinstance(name, basestring), "%r is not a string" % name
|
||||||
if util.is_hoppish(name):
|
lname = name.lower().strip()
|
||||||
lname = name.lower().strip()
|
if lname == "content-length":
|
||||||
if lname == "transfer-encoding":
|
self.clength = int(value)
|
||||||
if value.lower().strip() == "chunked":
|
elif util.is_hoppish(name):
|
||||||
self.chunked = True
|
#if lname == "transfer-encoding":
|
||||||
elif lname == "connection":
|
# self.te = value.lower().strip()
|
||||||
|
if lname == "connection":
|
||||||
# handle websocket
|
# handle websocket
|
||||||
if value.lower().strip() != "upgrade":
|
if value.lower().strip() != "upgrade":
|
||||||
continue
|
continue
|
||||||
@ -152,13 +157,26 @@ class Response(object):
|
|||||||
continue
|
continue
|
||||||
self.headers.append((name.strip(), str(value).strip()))
|
self.headers.append((name.strip(), str(value).strip()))
|
||||||
|
|
||||||
|
|
||||||
|
def is_chunked(self):
|
||||||
|
# maybe we should do this test if users expect this header
|
||||||
|
# to force chunked encoding
|
||||||
|
#if self.te == "chunked" and self.req.version > (1, 0):
|
||||||
|
# return True
|
||||||
|
if self.clength:
|
||||||
|
return False
|
||||||
|
elif self.req.version <= (1,0):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def default_headers(self):
|
def default_headers(self):
|
||||||
connection = "keep-alive"
|
connection = "keep-alive"
|
||||||
if self.should_close:
|
if self.should_close:
|
||||||
connection = "close"
|
connection = "close"
|
||||||
|
|
||||||
return [
|
return [
|
||||||
"HTTP/1.1 %s\r\n" % self.status,
|
"HTTP/%s.%s %s\r\n" % (self.req.version[0],
|
||||||
|
self.req.version[1], self.status),
|
||||||
"Server: %s\r\n" % self.version,
|
"Server: %s\r\n" % self.version,
|
||||||
"Date: %s\r\n" % util.http_date(),
|
"Date: %s\r\n" % util.http_date(),
|
||||||
"Connection: %s\r\n" % connection
|
"Connection: %s\r\n" % connection
|
||||||
@ -175,6 +193,19 @@ class Response(object):
|
|||||||
def write(self, arg):
|
def write(self, arg):
|
||||||
self.send_headers()
|
self.send_headers()
|
||||||
assert isinstance(arg, basestring), "%r is not a string." % arg
|
assert isinstance(arg, basestring), "%r is not a string." % arg
|
||||||
|
|
||||||
|
arglen = len(arg)
|
||||||
|
tosend = arglen
|
||||||
|
if self.clength is not None:
|
||||||
|
if self.sent >= self.clength:
|
||||||
|
# Never write more than self.clength bytes
|
||||||
|
return
|
||||||
|
|
||||||
|
tosend = min(self.clength - self.sent, tosend)
|
||||||
|
if tosend < arglen:
|
||||||
|
arg = arg[:tosend]
|
||||||
|
|
||||||
|
self.sent += tosend
|
||||||
util.write(self.sock, arg, self.chunked)
|
util.write(self.sock, arg, self.chunked)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user