2014-10-02 5 views
2

У меня есть рабочий Mojolicious сервер, который предоставляет данные с помощью HTML5 EventSource. Хорошо работает, но я хотел бы, чтобы данные были закодированы в формате gzip.Perl Mojolicious EventSource gzip output

Отправка сжатых данных с помощью записи дает CONTENT_DECODING_FAILED в инструментах Chrome Dev. Использование предлагаемого метода с «hook after_render», похоже, не работает с потоком событий. Как отправить gzip-кодированные данные с помощью EventSource и Mojolicious?

use Mojolicious::Lite; 
use Mojo::Redis; 
use IO::Compress::Gzip 'gzip'; 

my $redis = Mojo::Redis->new; 

get 'radar_events' => sub { 
    my $c = shift; 
    $c->render_later; 
    $c->inactivity_timeout(300); 
    $c->res->headers->content_type('text/event-stream'); 
    $c->res->headers->cache_control('no_cache'); 
    $c->res->headers->content_encoding('gzip'); 
    $c->res->headers->header('Access-Control-Allow-Origin' => '*'); 
    my $id = Mojo::IOLoop->recurring(
     5 => sub { 
      $c->delay(
       sub { 
        my $delay = shift; 
        $redis->get('radar', $delay->begin); 
       }, 
       sub { 
        my ($delay, $jstring) = @_; 
        my $buf = "event:rupdate\ndata: ".$jstring."\n\n"; 
        gzip \$jstring => \my $buf; 
        $c->write($buf); 
       } 
      ); 
     } 
    ); 
    $c->on(finish => sub { Mojo::IOLoop->remove($id) }); 
}; 

app->start; 

ответ

1

Я думаю, что это невозможно, как вы это делаете. Content-Encoding - это кодирование всего тела, которое содержит сообщения event:rupdate\n и data:..... Кроме того, каждое сообщение о событии представляет собой одну строку (см. the specification), поэтому вы не можете передавать двоичные данные (например, сжатые данные) таким образом.

Я не знаю, поддерживает ли браузер Content-Encoding потоками событий. Но если они это сделают, вам нужно будет предоставить один поток gzip, начиная с начала тела и заканчивая только после того, как вы закончите. И поскольку gzip буферизирует данные для достижения лучшего сжатия, вам нужно будет явно очистить объект gzip после каждого добавленного события.

+0

Спасибо Steffen. Я пробовал кодировать всю строку, и это не сработало. Он поддерживается, поскольку у меня есть PHP-версия сервера, который кодирует в формате gzip и работает ... Он явно покраснел, как вы сказали. – greytrader

+0

Вам нужно закодировать все тело в пределах одного потока gzip. Кодировки каждой строки отдельно недостаточно. –

+0

Я думал, что сделал, но имел и ошибку в моем коде ... Это работает спасибо! Измененный рабочий код выше. – greytrader

Смежные вопросы