tags:

views:

832

answers:

2

I'm trying to serve a gzipped version of a text/html page in Django, but Firefox is telling me there's a content encoding error.

NOTES:

  • I realize this is not a best practice and I'm most likely going to use mod_gzip. This is just a learning exercise to understand what's going on.
  • I know about the Django gzip middleware-- it has problems with binary files.

Here's my code:

rendered_page =  zlib.compress(template.render(context).encode('utf-8'))

response = HttpResponse(rendered_page)
response['Content-Encoding'] = 'gzip'
response['Content-Length'] = len(rendered_page)
return response

Am I missing something here? Is it possible that the content length is wrong? Are there additional headers I'm missing?

Thanks.

+8  A: 

zlib is a bit too low-level for this purpose. Here's how the GZip middleware itself does it (see compress_string in django.utils.text.py):

import cStringIO, gzip
zbuf = cStringIO.StringIO()
zfile = gzip.GzipFile(mode='wb', compresslevel=6, fileobj=zbuf)
zfile.write(template.render(context).encode('utf-8'))
zfile.close()

compressed_content = zbuf.getvalue()
response = HttpResponse(compressed_content)
response['Content-Encoding'] = 'gzip'
response['Content-Length'] = str(len(compressed_content))
return response

GZip uses zlib, but on its own zlib produces content that's improperly encoded for a browser seeing 'gzip' as the content encoding. Hope that helps!

Jarret Hardie
+2  A: 

You could also simply use django's gzip middleware:

Either by enabling the middleware in settings.py by adding:

MIDDLEWARE_CLASSES = (
 django.middleware.gzip.GZipMiddleware,
...

)

Or do it before you return a particular response. In your views.py, dec would be the handler for a certain url

from django.middleware.gzip import GZipMiddleware

gzip_middleware = GZipMiddleware()

 def dec(request, *args, **kwargs):
        response = func(request, *args, **kwargs)
        return gzip_middleware.process_response(request, response)
        return dec
Andres