是否可以将gzip压缩与服务器发送事件(SSE)一起使用?

mgu*_*arr 7 python html5 gzip bottle server-sent-events

我想知道是否可以为服务器发送事件启用gzip压缩(SSE;内容类型:文本/事件流).

根据这本书,似乎有可能:http: //chimera.labs.oreilly.com/books/1230000000545/ch16.html

但是我找不到任何带有gzip压缩的SSE的例子.我尝试将带有响应头字段Content-Encoding的 gzip压缩消息发送 到"gzip"但没有成功.

为了试验SSE,我正在使用瓶子框架+ gevent测试一个用Python制作的小型Web应用程序; 我只是运行瓶子WSGI服务器:

@bottle.get('/data_stream')
def stream_data():
    bottle.response.content_type = "text/event-stream"
    bottle.response.add_header("Connection", "keep-alive")
    bottle.response.add_header("Cache-Control", "no-cache")
    bottle.response.add_header("Content-Encoding", "gzip")
    while True:
        # new_data is a gevent AsyncResult object,
        # .get() just returns a data string when new
        # data is available
        data = new_data.get()
        yield zlib.compress("data: %s\n\n" % data)
        #yield "data: %s\n\n" % data
Run Code Online (Sandbox Code Playgroud)

没有压缩的代码(最后一行,注释)和没有gzip内容编码头字段的代码就像一个魅力.

编辑:感谢回复和其他问题:Python:创建流式gzip文件?,我设法解决了这个问题:

@bottle.route("/stream")
def stream_data():
    compressed_stream = zlib.compressobj()
    bottle.response.content_type = "text/event-stream"
    bottle.response.add_header("Connection", "keep-alive")
    bottle.response.add_header("Cache-Control", "no-cache, must-revalidate")
    bottle.response.add_header("Content-Encoding", "deflate")
    bottle.response.add_header("Transfer-Encoding", "chunked")
    while True:
        data = new_data.get()
        yield compressed_stream.compress("data: %s\n\n" % data)
        yield compressed_stream.flush(zlib.Z_SYNC_FLUSH)
Run Code Online (Sandbox Code Playgroud)

otu*_*tus 6

TL;DR:如果请求未缓存,您可能希望使用 zlib 并将 Content-Encoding 声明为“deflate”。仅此更改就可以使您的代码正常工作。


如果您将 Content-Encoding 声明为 gzip,则您需要实际使用 gzip。它们基于相同的压缩算法,但 gzip 有一些额外的帧。这有效,例如:

import gzip
import StringIO
from bottle import response, route
@route('/')
def get_data():
    response.add_header("Content-Encoding", "gzip")
    s = StringIO.StringIO()
    with gzip.GzipFile(fileobj=s, mode='w') as f:
        f.write('Hello World')
    return s.getvalue()
Run Code Online (Sandbox Code Playgroud)

不过,这只有在您使用实际文件作为缓存时才真正有意义。