是否可以用服务器发送事件(SSE)进行gzip压缩?[英] Is it possible to use gzip compression with Server-Sent Events (SSE)?

本文是小编为大家收集整理的关于是否可以用服务器发送事件(SSE)进行gzip压缩?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我想知道是否可以启用GZIP压缩 对于服务器范围的事件(SSE; content-type:text/event-stream).

根据这本书,似乎有可能:

,但我找不到带有GZIP压缩的SSE的任何例子.我尝试过了 在响应标头字段中发送gzzed邮件 内容编码设置为" gzip"而无需成功.

要试验SSE,我正在测试一个小型Web应用程序 用瓶子框架 + gevent制成;我刚跑步 瓶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

无压缩的代码(最后一行,注释),没有GZIP 内容编码的标题字段就像魅力一样工作.

编辑:感谢答复和另一个问题: python:创建一个类似gzip'd file的?,我设法解决了问题:

@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)

推荐答案

tl; dr:如果未缓存请求,则可能要使用zlib并声明内容编码为'deflate'.仅此更改就应该使您的代码正常工作.


如果您声明内容编码为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()

,只有在使用实际文件作为缓存时才真正有意义.

其他推荐答案

您还可以使用中间件,因此您不必担心每种方法的响应.这是我最近使用的.

https://code.google.com/p/ibkon-wsgi -gzip-middleware/

这就是我的使用方式(我正在使用gevent服务器使用botter.py)

from gzip_middleware import Gzipper
import bottle
app = Gzipper(bottle.app())
run(app = app, host='0.0.0.0', port=8080, server='gevent')

对于此特定库,您可以通过修改DEFAULT_COMPRESSABLES variable例如

来设置要压缩的w/c类型的响应类型
DEFAULT_COMPRESSABLES = set(['text/plain', 'text/html', 'text/css',
'application/json', 'application/x-javascript', 'text/xml',
'application/xml', 'application/xml+rss', 'text/javascript',     
'image/gif'])

所有响应都会通过中间件并进行GZZE,而无需修改您的现有代码.默认情况下,它压缩了其内容类型属于DEFAULT_COMPRESSABLES且内容长度大于200个字符的响应.

本文地址:https://www.itbaoku.cn/post/882607.html

问题描述

I would like to know if it is possible to enable gzip compression for Server-Sent Events (SSE ; Content-Type: text/event-stream).

It seems it is possible, according to this book: http://chimera.labs.oreilly.com/books/1230000000545/ch16.html

But I can't find any example of SSE with gzip compression. I tried to send gzipped messages with the response header field Content-Encoding set to "gzip" without success.

For experimenting around SSE, I am testing a small web application made in Python with the bottle framework + gevent ; I am just running the bottle WSGI server:

@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

The code without compression (last line, commented) and without gzip content-encoding header field works like a charm.

EDIT: thanks to the reply and to this other question: Python: Creating a streaming gzip'd file-like?, I managed to solve the problem:

@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)

推荐答案

TL;DR: If the requests are not cached, you likely want to use zlib and declare Content-Encoding to be 'deflate'. That change alone should make your code work.


If you declare Content-Encoding to be gzip, you need to actually use gzip. They are based on the the same compression algorithm, but gzip has some extra framing. This works, for example:

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()

That only really makes sense if you use an actual file as a cache, though.

其他推荐答案

There's also middleware you can use so you don't need to worry about gzipping responses for each of your methods. Here's one I used recently.

https://code.google.com/p/ibkon-wsgi-gzip-middleware/

This is how I used it (I'm using bottle.py with the gevent server)

from gzip_middleware import Gzipper
import bottle
app = Gzipper(bottle.app())
run(app = app, host='0.0.0.0', port=8080, server='gevent')

For this particular library, you can set w/c types of responses you want to compress by modifying the DEFAULT_COMPRESSABLES variable for example

DEFAULT_COMPRESSABLES = set(['text/plain', 'text/html', 'text/css',
'application/json', 'application/x-javascript', 'text/xml',
'application/xml', 'application/xml+rss', 'text/javascript',     
'image/gif'])

All responses go through the middleware and get gzipped without modifying your existing code. By default, it compresses responses whose content-type belongs to DEFAULT_COMPRESSABLES and whose content-length is greater than 200 characters.