2014-05-20 19 views
7

Tôi muốn biết liệu có thể bật tính năng nén gzip cho Sự kiện được Máy chủ gửi (SSE; Loại Nội dung: văn bản/sự kiện-luồng).Có thể sử dụng nén gzip với Sự kiện Máy chủ-Gửi (SSE) không?

Có vẻ như nó là có thể, theo cuốn sách này: http://chimera.labs.oreilly.com/books/1230000000545/ch16.html

Nhưng tôi không thể tìm thấy bất kỳ ví dụ về SSE với khả năng nén gzip. Tôi đã cố gắng để gửi thư gzipped với trường tiêu đề phản hồi Mã hóa nội dung đặt thành "gzip" mà không thành công.

Để thử nghiệm xung quanh SSE, tôi đang thử nghiệm một ứng dụng web nhỏ được tạo bằng Python với khung chai + gevent; Tôi chỉ chạy server chai 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 

Các mã mà không nén (dòng cuối cùng, nhận xét) và không có gzip lĩnh vực tiêu đề nội dung mã hóa hoạt động như một nét duyên dáng.

EDIT: nhờ vào các câu trả lời và câu hỏi khác này: Python: Creating a streaming gzip'd file-like?, tôi quản lý để giải quyết vấn đề:

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

Trả lời

4

TL; DR: Nếu yêu cầu không được lưu trữ, bạn có thể muốn sử dụng zlib và khai báo Content-Encoding là 'deflate'. Chỉ riêng thay đổi đó sẽ làm cho mã của bạn hoạt động.


Nếu bạn khai báo Mã hóa nội dung thành gzip, bạn cần sử dụng gzip. Chúng dựa trên cùng một thuật toán nén, nhưng gzip có thêm một số khung. Công cụ này hoạt động, ví dụ:

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

Điều đó chỉ thực sự có ý nghĩa nếu bạn sử dụng tệp thực tế làm bộ nhớ cache.

+0

Cảm ơn bạn đã giải thích. Thật vậy, việc thay đổi Content-Encoding thành deflate giúp một chút: thông báo đầu tiên được xử lý ở phía máy khách. Nhưng chỉ có lần đầu tiên: (Bạn có bất cứ ý tưởng tại sao? Cảm ơn trước – mguijarr

+0

Bạn đang cố gắng gọi nén độc lập cho mỗi khối dữ liệu? Tôi không nghĩ rằng sẽ làm việc.Tất cả các dữ liệu nên được trong một dòng nén duy nhất.Điều đó có nghĩa là gzip với giao diện trực tuyến của nó thực sự có thể là con đường để đi. Tuy nhiên, tôi sẽ cần phải xem thêm mã của bạn để cung cấp các con trỏ cụ thể. – otus

+0

Cảm ơn một triệu; cuối cùng nó hoạt động! Tôi đã chỉnh sửa câu hỏi của mình để nói những gì tôi phải thay đổi. – mguijarr

2

Cũng có phần mềm trung gian mà bạn có thể sử dụng, do đó bạn không cần phải lo lắng về các phản hồi gzipping cho từng phương pháp của mình. Đây là cái tôi đã sử dụng gần đây.

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

Đây là cách tôi đã sử dụng nó (Tôi đang sử dụng bottle.py với máy chủ gevent)

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

Đối với thư viện đặc biệt này, bạn có thể đặt w/c loại trả lời bạn muốn nén bằng cách sửa đổi DEFAULT_COMPRESSABLES variable ví dụ

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']) 

Tất cả các phản ứng đi qua các trung gian và nhận được gzip mà không sửa đổi mã hiện tại của bạn. Theo mặc định, nó nén các phản hồi có loại nội dung thuộc về DEFAULT_COMPRESSABLES và có độ dài nội dung lớn hơn 200 ký tự.

+0

Cảm ơn câu trả lời của bạn – mguijarr

Các vấn đề liên quan