Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use gzip encoding with wsgi application?

I'm trying to output gzip encoded strings using wsgi, these are my attempts but unfortunately browser only decodes the first string, any help?

test 1:

import zlib

def application(environ, start_response):
    headers = [('Content-Type', 'text/html; charset=utf-8'),('Content-Encoding', 'gzip')]
    data = b'\x1f\x8b\x08\x00\x00\x00\x00\x00'
    data += zlib.compress(b'test')[:-4]
    data += zlib.compress(b'test2')[:-4]
    headers.append(('Content-Length', str(len(data))))
    start_response('200 OK',headers)
    return [data]

test 2:

import zlib

def application(environ, start_response):
    headers = [('Content-Type', 'text/html; charset=utf-8'),('Content-Encoding', 'gzip')]
    data = b'\x1f\x8b\x08\x00\x00\x00\x00\x00'
    data += zlib.compress(b'test')
    data += zlib.compress(b'test2')
    headers.append(('Content-Length', str(len(data))))
    start_response('200 OK',headers)
    return [data]

test 3:

import zlib

def application(environ, start_response):
    headers = [('Content-Type', 'text/html; charset=utf-8'),('Content-Encoding', 'gzip')]
    start_response('200 OK',headers)
    yield b'\x1f\x8b\x08\x00\x00\x00\x00\x00'
    yield zlib.compress(b'test')[:-4]
    yield zlib.compress(b'test2')[:-4]

test 4:

import zlib

def application(environ, start_response):
    headers = [('Content-Type', 'text/html; charset=utf-8'),('Content-Encoding', 'gzip')]
    start_response('200 OK',headers)
    yield b'\x1f\x8b\x08\x00\x00\x00\x00\x00'
    yield zlib.compress(b'test')
    yield zlib.compress(b'test2')

test 5:

import gzip

def application(environ, start_response):
    headers = [('Content-Type', 'text/html; charset=utf-8'),('Content-Encoding', 'gzip')]
    start_response('200 OK',headers)
    yield gzip.compress(b'test')
    yield gzip.compress(b'test2')

1 Answers

I think the problem is the following:

 gzip.compress(b'test')

return a string with

 header  content  THE END 

in it.

This means when you read it the uncompressing will only return the b'test'. Try it yourself.

Two solutions depending on what you want to achieve:

  1. Create a multipart message. Every yield is a new document
  2. compress does this:

    def compress(data, compresslevel=9):
    
        """Compress data in one shot and return the compressed string.
        Optional argument is the compression level, in range of 0-9.
        """
        buf = io.BytesIO()
        with GzipFile(fileobj=buf, mode='wb', compresslevel=compresslevel) as f:
            f.write(data)
        return buf.getvalue()
    

    Do the something like this:

    import gzip, io
    
    def application(environ, start_response):
        headers = [('Content-Type', 'text/html; charset=utf-8'),('Content-Encoding',     'gzip')]
        start_response('200 OK',headers)
        buf = io.BytesIO()
        with GzipFile(fileobj=buf, mode='wb') as f:
             f.write(b'test')
             f.write(b'test2')
        return buf
    
like image 198
User Avatar answered Dec 08 '25 15:12

User