Skip to content
Browse files

content-typeとvaryのオプション付ける

  • Loading branch information...
1 parent b9dc7ac commit 5d01bf96a7b91fbcaff4a3980e254302712608ea Masahiro Nagano committed
Showing with 221 additions and 1 deletion.
  1. +3 −0 .gitignore
  2. +1 −0 Makefile.PL
  3. +30 −1 lib/Plack/Middleware/Deflater.pm
  4. +89 −0 t/content_type.t
  5. +1 −0 t/deflater.t
  6. +97 −0 t/no_accept.t
View
3 .gitignore
@@ -3,3 +3,6 @@ Makefile
inc/
pm_to_blib
*~
+blib
+
+
View
1 Makefile.PL
@@ -6,6 +6,7 @@ build_requires 'Test::More';
requires 'Plack';
requires 'IO::Compress::Gzip';
requires 'IO::Compress::Deflate';
+requires 'Text::Glob';
use_test_base;
auto_include_deps;
author_tests('xt');
View
31 lib/Plack/Middleware/Deflater.pm
@@ -3,10 +3,25 @@ use strict;
use 5.008001;
our $VERSION = '0.03';
use parent qw(Plack::Middleware);
+use Plack::Util::Accessor qw( content_type vary_user_agent);
use IO::Compress::Deflate;
use IO::Compress::Gzip;
use Plack::Util;
+use Text::Glob qw/glob_to_regex/;
+
+sub prepare_app {
+ my $self = shift;
+ if ( my $match_cts = $self->content_type ) {
+ my @matches;
+ $match_cts = [$match_cts] if ! ref $match_cts;
+ for my $match_ct ( @{$match_cts} ) {
+ my $re = glob_to_regex($match_ct);
+ push @matches, $re;
+ }
+ $self->content_type(\@matches);
+ }
+}
sub call {
my($self, $env) = @_;
@@ -20,11 +35,24 @@ sub call {
return unless defined $res->[2];
my $h = Plack::Util::headers($res->[1]);
+ if ( my $match_cts = $self->content_type ) {
+ my $content_type = $h->get('Content-Type') || '';
+ $content_type =~ s/(;.*)$//;
+ my $match=0;
+ for my $match_ct ( @{$match_cts} ) {
+ if ( $content_type =~ m!^${match_ct}$! ) {
+ $match++;
+ last;
+ }
+ }
+ return unless $match;
+ }
+
if (Plack::Util::status_with_no_entity_body($res->[0]) or
$h->exists('Cache-Control') && $h->get('Cache-Control') =~ /\bno-transform\b/) {
return;
}
-
+
# TODO check quality
my $encoding = 'identity';
if ( defined $env->{HTTP_ACCEPT_ENCODING} ) {
@@ -38,6 +66,7 @@ sub call {
my @vary = split /\s*,\s*/, ($h->get('Vary') || '');
push @vary, 'Accept-Encoding';
+ push @vary, 'User-Agent' if $self->vary_user_agent;
$h->set('Vary' => join(",", @vary));
my $encoder;
View
89 t/content_type.t
@@ -0,0 +1,89 @@
+use strict;
+use Test::More;
+use Test::Requires qw(IO::Handle::Util);
+use IO::Handle::Util qw(:io_from);
+use HTTP::Request::Common;
+use Plack::Builder;
+use Plack::Test;
+use Plack::Middleware::Deflater;
+$Plack::Test::Impl = "Server";
+
+
+my $app = builder {
+ enable 'Deflater', content_type => 'text/*';
+ sub { [200, [ 'Content-Type' => 'text/plain' ], [ "Hello World" ]] }
+};
+test_psgi
+ app => $app,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ is $res->content_encoding, 'gzip';
+ };
+
+my $app2 = builder {
+ enable 'Deflater', content_type => 'text/*';
+ sub { [200, [ 'Content-Type' => 'text/html; charset=UTF-8' ], [ "Hello World" ]] }
+};
+test_psgi
+ app => $app2,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ is $res->content_encoding, 'gzip';
+ };
+
+my $app3 = builder {
+ enable 'Deflater', content_type => 'text/*';
+ sub { [200, [ 'Content-Type' => 'image/jpeg' ], [ "Hello World" ]] }
+};
+test_psgi
+ app => $app3,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ isnt $res->content_encoding, 'gzip';
+ };
+
+my $app4 = builder {
+ enable 'Deflater', content_type => ['text/*','application/javascript'];
+ sub { [200, [ 'Content-Type' => 'application/javascript' ], [ "Hello World" ]] }
+};
+test_psgi
+ app => $app4,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ is $res->content_encoding, 'gzip';
+ };
+
+my $app5 = builder {
+ enable 'Deflater', content_type => ['text/*','application/javascript'];
+ sub { [200, [ 'Content-Type' => 'image/gif' ], [ "Hello World" ]] }
+};
+test_psgi
+ app => $app5,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ isnt $res->content_encoding, 'gzip';
+ };
+
+
+
+done_testing;
View
1 t/deflater.t
@@ -29,6 +29,7 @@ test_psgi app => Plack::Middleware::Deflater->wrap($app), client => sub {
my $res = $cb->($req);
is $res->decoded_content, 'Hello World';
is $res->content_encoding, 'gzip';
+ like $res->header('Vary'), qr/Accept-Encoding/
}
};
View
97 t/no_accept.t
@@ -0,0 +1,97 @@
+use strict;
+use Test::More;
+use Test::Requires qw(IO::Handle::Util);
+use IO::Handle::Util qw(:io_from);
+use HTTP::Request::Common;
+use Plack::Builder;
+use Plack::Test;
+use Plack::Middleware::Deflater;
+$Plack::Test::Impl = "Server";
+
+
+my $app = builder {
+ enable 'Deflater', content_type => 'image/*', vary_user_agent => 1;;
+ sub { [200, [ 'Content-Type' => 'text/plain' ], [ "Hello World" ]] }
+};
+test_psgi
+ app => $app,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ isnt $res->content_encoding, 'gzip';
+ unlike $res->header('Vary') || '', qr/Accept-Encoding/;
+ unlike $res->header('Vary') || '', qr/User-Agent/;
+ };
+
+my $app2 = builder {
+ enable sub {
+ my $cb = shift;
+ sub {
+ my $env = shift;
+ $env->{HTTP_ACCEPT_ENCODING} =~ s/(gzip|deflate)//gi if $env->{HTTP_USER_AGENT} =~ m!^Mozilla/4! and $env->{HTTP_USER_AGENT} !~ m!\bMSIE\s(7|8)!;
+ $cb->($env);
+ }
+ };
+ enable 'Deflater', content_type => 'text/*', vary_user_agent => 1;
+ sub { [200, [ 'Content-Type' => 'text/plain' ], [ "Hello World" ]] }
+};
+
+test_psgi
+ app => $app2,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ is $res->content_encoding, 'gzip';
+ like $res->header('Vary'), qr/Accept-Encoding/;
+ like $res->header('Vary'), qr/User-Agent/;
+ };
+
+test_psgi
+ app => $app2,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ $req->user_agent("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 6.0; Trident/4.0)");
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ isnt $res->content_encoding, 'gzip';
+ like $res->header('Vary'), qr/Accept-Encoding/;
+ like $res->header('Vary'), qr/User-Agent/;
+ };
+
+test_psgi
+ app => $app2,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ $req->user_agent("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0)");
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ is $res->content_encoding, 'gzip';
+ like $res->header('Vary'), qr/Accept-Encoding/;
+ like $res->header('Vary'), qr/User-Agent/;
+ };
+
+test_psgi
+ app => $app2,
+ client => sub {
+ my $cb = shift;
+ my $req = HTTP::Request->new(GET => "http://localhost/");
+ $req->accept_decodable;
+ $req->user_agent("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
+ my $res = $cb->($req);
+ is $res->decoded_content, 'Hello World';
+ is $res->content_encoding, 'gzip';
+ like $res->header('Vary'), qr/Accept-Encoding/;
+ like $res->header('Vary'), qr/User-Agent/;
+ };
+
+
+done_testing;

1 comment on commit 5d01bf9

@miyagawa

Update docs too?

Please sign in to comment.
Something went wrong with that request. Please try again.