miyagawa (owner)

Revisions

gist: 212432 Download_button fork
public
Public Clone URL: git://gist.github.com/212432.git
Embed All Files: show embed
Text only #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
diff --git a/lib/Plack/Middleware.pm b/lib/Plack/Middleware.pm
index a40c0c1..8f6d463 100644
--- a/lib/Plack/Middleware.pm
+++ b/lib/Plack/Middleware.pm
@@ -3,6 +3,7 @@ use strict;
 use warnings;
 use parent qw/Class::Accessor::Fast/;
 use Carp ();
+use Plack::Util;
 use overload '&{}' => sub { shift->to_app(@_) }, fallback => 1;
 
 __PACKAGE__->mk_accessors(qw/app/);
@@ -32,16 +33,42 @@ sub to_app {
 sub response_cb {
     my($self, $res, $cb) = @_;
 
+ my $body_filter = sub {
+ my($cb, $res) = @_;
+ my $filter_cb = $cb->($res);
+ # If response_cb returns a callback, treat it as a $body filter
+ if (defined $filter_cb && ref $filter_cb eq 'CODE') {
+ if (defined $res->[2]) {
+ my $body = $res->[2];
+ my $getline = ref $body eq 'ARRAY' ? sub { shift @$body } : sub { $body->getline };
+ $res->[2] = Plack::Util::inline_object
+ getline => sub { $filter_cb->($getline->()) },
+ close => sub { $body->close if ref $body ne 'ARRAY' };
+ } else {
+ return $filter_cb;
+ }
+ }
+ };
+
     if (ref $res eq 'ARRAY') {
- $cb->($res);
+ $body_filter->($cb, $res);
         return $res;
     } elsif (ref $res eq 'CODE') {
         return sub {
             my $respond = shift;
             $res->(sub {
                 my $res = shift;
- $cb->($res);
- $respond->($res);
+ my $filter_cb = $body_filter->($cb, $res);
+ if ($filter_cb) {
+ my $writer = $respond->($res);
+ if ($writer) {
+ return Plack::Util::inline_object
+ write => sub { $writer->write($filter_cb->(@_)) },
+ close => sub { $writer->close };
+ }
+ } else {
+ return $respond->($res);
+ }
             });
         };
     }
diff --git a/lib/Plack/Middleware/Chunked.pm b/lib/Plack/Middleware/Chunked.pm
index 6e54464..139a5d0 100644
--- a/lib/Plack/Middleware/Chunked.pm
+++ b/lib/Plack/Middleware/Chunked.pm
@@ -13,25 +13,20 @@ sub call {
         if ($env->{'SERVER_PROTOCOL'} ne 'HTTP/1.0' and
             ! Plack::Util::status_with_no_entity_body($res->[0]) and
             ! $h->exists('Content-Length') and
- ! $h->exists('Transfer-Encoding') and
- defined $res->[2]
+ ! $h->exists('Transfer-Encoding')
         ) {
             $h->set('Transfer-Encoding' => 'chunked');
- my $body = $res->[2];
- my $getline = ref $body eq 'ARRAY' ? sub { shift @$body } : sub { $body->getline };
             my $done;
- $res->[2] = Plack::Util::inline_object
- getline => sub {
- my $chunk = $getline->();
- return if $done;
- unless (defined $chunk) {
- $done = 1;
- return "0\015\012\015\012";
- }
- return '' unless length $chunk;
- return sprintf('%x', length $chunk) . "\015\012$chunk\015\012";
- },
- close => sub { $body->close if ref $body ne 'ARRAY' };
+ return sub {
+ my $chunk = shift;
+ return if $done;
+ unless (defined $chunk) {
+ $done = 1;
+ return "0\015\012\015\012";
+ }
+ return '' unless length $chunk;
+ return sprintf('%x', length $chunk) . "\015\012$chunk\015\012";
+ };
         }
     });
 }
diff --git a/lib/Plack/Middleware/SimpleContentFilter.pm b/lib/Plack/Middleware/SimpleContentFilter.pm
index 8b07dc6..e43d443 100644
--- a/lib/Plack/Middleware/SimpleContentFilter.pm
+++ b/lib/Plack/Middleware/SimpleContentFilter.pm
@@ -9,30 +9,20 @@ use Plack::Util;
 sub call {
     my $self = shift;
 
- my($status, $header, $body) = @{$self->app->(@_)};
-
- my $h = Plack::Util::headers($header);
-
- unless ($h->get('Content-Type') =~ m!^text/!) {
- return [ $status, $header, $body ]
- }
-
- my $getline = ref $body eq 'ARRAY' ? sub { shift @$body } : sub { $body->getline };
-
- my $body_filter = Plack::Util::inline_object(
- getline => sub {
- my $line = $getline->();
- return unless defined $line;
- local $_ = $line;
- $self->filter->();
- return $_;
- },
- close => sub {
- $body->close unless ref $body eq 'ARRAY';
- },
- );
-
- return [ $status, $header, $body_filter ];
+ my $res = $self->app->(@_);
+ $self->response_cb($res, sub {
+ my $res = shift;
+ my $h = Plack::Util::headers($res->[1]);
+ if ($h->get('Content-Type') =~ m!^text/!) {
+ return sub {
+ my $chunk = shift;
+ return unless defined $chunk;
+ local $_ = $chunk;
+ $self->filter->();
+ return $_;
+ };
+ }
+ });
 }
 
 1;
 
Text only #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
diff --git a/lib/Tatsumaki/Handler.pm b/lib/Tatsumaki/Handler.pm
index 14b7260..4ce9e13 100644
--- a/lib/Tatsumaki/Handler.pm
+++ b/lib/Tatsumaki/Handler.pm
@@ -111,6 +111,8 @@ sub finish {
     $self->write($chunk) if defined $chunk;
     $self->flush(1);
     if ($self->writer) {
+ # HACK: to cleanly finish chunk
+ $self->writer->write(undef);
         $self->writer->close;
     } elsif ($self->condvar) {
         $self->condvar->send($self->response->finalize);