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:
benoitc 2011-01-09 13:54:24 +01:00
parent cd726f6d8c
commit 39f5d313f7

View File

@ -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):