diff --git a/gunicorn/http/wsgi.py b/gunicorn/http/wsgi.py index 11db0199..68c2d94c 100644 --- a/gunicorn/http/wsgi.py +++ b/gunicorn/http/wsgi.py @@ -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):