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.headers = []
|
||||
self.headers_sent = False
|
||||
self.clength = -1
|
||||
#self.te = None
|
||||
self.sent = 0
|
||||
|
||||
def force_close(self):
|
||||
self.should_close = True
|
||||
@ -133,17 +136,19 @@ class Response(object):
|
||||
|
||||
self.status = status
|
||||
self.process_headers(headers)
|
||||
self.chunked = self.is_chunked()
|
||||
return self.write
|
||||
|
||||
def process_headers(self, headers):
|
||||
for name, value in headers:
|
||||
assert isinstance(name, basestring), "%r is not a string" % name
|
||||
if util.is_hoppish(name):
|
||||
lname = name.lower().strip()
|
||||
if lname == "transfer-encoding":
|
||||
if value.lower().strip() == "chunked":
|
||||
self.chunked = True
|
||||
elif lname == "connection":
|
||||
lname = name.lower().strip()
|
||||
if lname == "content-length":
|
||||
self.clength = int(value)
|
||||
elif util.is_hoppish(name):
|
||||
#if lname == "transfer-encoding":
|
||||
# self.te = value.lower().strip()
|
||||
if lname == "connection":
|
||||
# handle websocket
|
||||
if value.lower().strip() != "upgrade":
|
||||
continue
|
||||
@ -152,13 +157,26 @@ class Response(object):
|
||||
continue
|
||||
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):
|
||||
connection = "keep-alive"
|
||||
if self.should_close:
|
||||
connection = "close"
|
||||
|
||||
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,
|
||||
"Date: %s\r\n" % util.http_date(),
|
||||
"Connection: %s\r\n" % connection
|
||||
@ -175,6 +193,19 @@ class Response(object):
|
||||
def write(self, arg):
|
||||
self.send_headers()
|
||||
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)
|
||||
|
||||
def close(self):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user