From b279b75c876e819034e6c56f3bf3b0c4b9843636 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Mon, 17 Dec 2007 11:46:48 +0000 Subject: [PATCH] Fixed #5596 -- Changed the static view for the development server so that Django doesn't crash if somebody tries to serve a 200MB file. Patch from eibaan. git-svn-id: http://code.djangoproject.com/svn/django/trunk@6939 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/servers/basehttp.py | 16 ++++++++++++++-- django/views/static.py | 3 ++- tests/regressiontests/views/media/file.unknown | 1 + tests/regressiontests/views/tests/static.py | 8 ++++++-- 4 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 tests/regressiontests/views/media/file.unknown diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index e98957da2c30e..05f8756655f64 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -398,8 +398,20 @@ def write(self, data): self.bytes_sent += len(data) # XXX check Content-Length and truncate if too many bytes written? - self._write(data) - self._flush() + + # If data is too large, socket will choke, so write chunks no larger + # than 32MB at a time. + length = len(data) + if length > 33554432: + offset = 0 + while offset < length: + chunk_size = min(33554432, length) + self._write(data[offset:offset+chunk_size]) + self._flush() + offset += chunk_size + else: + self._write(data) + self._flush() def sendfile(self): """Platform-specific file transmission diff --git a/django/views/static.py b/django/views/static.py index 8095fc9231f4d..5a4d3ab55cb6f 100644 --- a/django/views/static.py +++ b/django/views/static.py @@ -59,10 +59,11 @@ def serve(request, path, document_root=None, show_indexes=False): if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'), statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]): return HttpResponseNotModified() - mimetype = mimetypes.guess_type(fullpath)[0] + mimetype = mimetypes.guess_type(fullpath)[0] or 'application/octet-stream' contents = open(fullpath, 'rb').read() response = HttpResponse(contents, mimetype=mimetype) response["Last-Modified"] = http_date(statobj[stat.ST_MTIME]) + response["Content-Length"] = len(contents) return response DEFAULT_DIRECTORY_INDEX_TEMPLATE = """ diff --git a/tests/regressiontests/views/media/file.unknown b/tests/regressiontests/views/media/file.unknown new file mode 100644 index 0000000000000..77dcda89708ef --- /dev/null +++ b/tests/regressiontests/views/media/file.unknown @@ -0,0 +1 @@ +An unknown file extension. diff --git a/tests/regressiontests/views/tests/static.py b/tests/regressiontests/views/tests/static.py index c731b249e8a6b..d7e87d19d2dd8 100644 --- a/tests/regressiontests/views/tests/static.py +++ b/tests/regressiontests/views/tests/static.py @@ -13,11 +13,15 @@ def test_serve(self): response = self.client.get('/views/site_media/%s' % filename) file = open(path.join(media_dir, filename)) self.assertEquals(file.read(), response.content) + self.assertEquals(len(response.content), int(response['Content-Length'])) + + def test_unknown_mime_type(self): + response = self.client.get('/views/site_media/file.unknown') + self.assertEquals('application/octet-stream', response['Content-Type']) def test_copes_with_empty_path_component(self): file_name = 'file.txt' response = self.client.get('/views/site_media//%s' % file_name) file = open(path.join(media_dir, file_name)) self.assertEquals(file.read(), response.content) - - +