Bug found 1.3.0 twisted.web.static module

This bug has occurs when a client request partial content of a static.File resource. There are three problems. 1) The Content-Length header value is off by 1. For example a request with a Range: bytes=0-1999 would yield Content-Length of 1999 when it should actually be Content-Length: 2000. 2) The Content-Range response header was generated incorrectly. For example the request with a Range: bytes=0-1999 header for a file of 100000 bytes in size would yield a Content-Range header like Content-Range: bytes 0-1999/1999, when it should be Content-Range: bytes 0-1999/100000. 3) The ASISProcessor incorrectly instantiated the File instance by passing a registry parameter to the defaultType argument. The diffs are as follows: diff -u static.py.orig static.py --- static.py.orig 2005-02-09 18:52:35.422310000 -0800 +++ static.py 2005-02-09 19:11:23.181906600 -0800 @@ -319,7 +319,7 @@ return self.redirect(request) #for content-length - fsize = size = self.getFileSize() + fsize = csize = self.getFileSize() request.setHeader('accept-ranges','bytes') @@ -350,20 +350,19 @@ "Syntactically invalid http range header!" start, end = string.split(bytesrange[1],'-') if start: - f.seek(int(start)) + start = int(start) + f.seek(start) if end: - end = int(end) - size = end + csize = int(end) - start + 1 else: - end = size + csize -= start request.setResponseCode(http.PARTIAL_CONTENT) - request.setHeader('content-range',"bytes %s-%s/%s " % ( - str(start), str(end), str(size))) - #content-length should be the actual size of the stuff we're - #sending, not the full size of the on-server entity. - fsize = end - int(start) + request.setHeader('content-range',"bytes %s-%s/%s " % \ + (start, end, fsize)) + #content-length should be the actual size of the stuff we're + #sending, not the full size of the on-server entity. + request.setHeader('content-length', str(csize)) - request.setHeader('content-length', str(fsize)) except: traceback.print_exc(file=log.logfile) @@ -371,7 +370,7 @@ return '' # return data - FileTransfer(f, size, request) + FileTransfer(f, csize, request) # and make sure the connection doesn't get closed return server.NOT_DONE_YET @@ -422,17 +421,16 @@ self.file = file self.size = size self.request = request - self.written = self.file.tell() request.registerProducer(self, 0) def resumeProducing(self): if not self.request: return - data = self.file.read(min(abstract.FileDescriptor.bufferSize, self.size - self.written)) + data = self.file.read(min(abstract.FileDescriptor.bufferSize, self.size)) if data: - self.written += len(data) self.request.write(data) - if self.file.tell() == self.size: + self.size -= len(data) + if self.size <= 0: self.request.unregisterProducer() self.request.finish() self.request = None @@ -473,5 +471,5 @@ def render(self, request): request.startedWriting = 1 - res = static.File(self.path, self.registry) + res = static.File(self.path, registry=self.registry) return res.render(request)

Mike Marchionna wrote:
1) The Content-Length header value is off by 1. For example a request with a Range: bytes=0-1999 would yield Content-Length of 1999 when it should actually be Content-Length: 2000.
2) The Content-Range response header was generated incorrectly. For example the request with a Range: bytes=0-1999 header for a file of 100000 bytes in size would yield a Content-Range header like Content-Range: bytes 0-1999/1999, when it should be Content-Range: bytes 0-1999/100000.
3) The ASISProcessor incorrectly instantiated the File instance by passing a registry parameter to the defaultType argument.
1) and 2) ------------------------------------------------------------------------ r12615 | foom | 2004-11-30 01:23:40 +0200 (Tue, 30 Nov 2004) | 2 lines remove range support because it's horribly broken. ------------------------------------------------------------------------ 3) ------------------------------------------------------------------------ r12816 | mesozoic | 2005-01-03 01:33:41 +0200 (Mon, 03 Jan 2005) | 2 lines Make sure ASISProcessor actually works. ------------------------------------------------------------------------

Tommi Virtanen wrote:
Mike Marchionna wrote:
1) The Content-Length header value is off by 1. For example a request with a Range: bytes=0-1999 would yield Content-Length of 1999 when it should actually be Content-Length: 2000.
2) The Content-Range response header was generated incorrectly. For example the request with a Range: bytes=0-1999 header for a file of 100000 bytes in size would yield a Content-Range header like Content-Range: bytes 0-1999/1999, when it should be Content-Range: bytes 0-1999/100000.
Added .todo unit tests to twisted.web.test.test_static. Fixed the exact same bugs, and added unit test, to nevow.
participants (2)
-
Mike Marchionna
-
Tommi Virtanen