Header-injection security fix, without perltidy
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Response.pm
CommitLineData
fc7ec1d9 1package Catalyst::Response;
2
059c085b 3use Moose;
6680c772 4use HTTP::Headers;
faa02805 5use Moose::Util::TypeConstraints;
6use namespace::autoclean;
fc7ec1d9 7
531f1ab6 8with 'MooseX::Emulate::Class::Accessor::Fast';
9
faa02805 10has _response_cb => (
11 is => 'ro',
2524941e 12 isa => 'CodeRef',
faa02805 13 writer => '_set_response_cb',
14 clearer => '_clear_response_cb',
15 predicate => '_has_response_cb',
16);
17
18subtype 'Catalyst::Engine::Types::Writer',
19 as duck_type([qw(write close)]);
20
21has _writer => (
22 is => 'ro',
46fff667 23 isa => 'Catalyst::Engine::Types::Writer', #Pointless since we control how this is built
24 #writer => '_set_writer', Now that its lazy I think this is safe to remove
faa02805 25 clearer => '_clear_writer',
26 predicate => '_has_writer',
46fff667 27 lazy => 1,
28 builder => '_build_writer',
faa02805 29);
30
46fff667 31sub _build_writer {
32 my $self = shift;
33
34 ## These two lines are probably crap now...
35 $self->_context->finalize_headers unless
36 $self->finalized_headers;
37
38 my @headers;
39 $self->headers->scan(sub { push @headers, @_ });
40
41 my $writer = $self->_response_cb->([ $self->status, \@headers ]);
42 $self->_clear_response_cb;
43
44 return $writer;
45}
46
e37f92f5 47has write_fh => (
48 is=>'ro',
a3c9ab76 49 predicate=>'_has_write_fh',
eb1f4b49 50 lazy=>1,
1f2a8069 51 builder=>'_build_write_fh',
52);
53
46fff667 54sub _build_write_fh { shift ->_writer }
e37f92f5 55
56sub DEMOLISH {
57 my $self = shift;
a3c9ab76 58 return if $self->_has_write_fh;
e37f92f5 59 if($self->_has_writer) {
60 $self->_writer->close
61 }
62}
faa02805 63
6680c772 64has cookies => (is => 'rw', default => sub { {} });
ffb43803 65has body => (is => 'rw', default => undef);
66sub has_body { defined($_[0]->body) }
99a543ee 67
2524941e 68has location => (is => 'rw', writer => '_set_location');
6680c772 69has status => (is => 'rw', default => 200);
70has finalized_headers => (is => 'rw', default => 0);
059c085b 71has headers => (
72 is => 'rw',
9c331634 73 isa => 'HTTP::Headers',
059c085b 74 handles => [qw(content_encoding content_length content_type header)],
6680c772 75 default => sub { HTTP::Headers->new() },
76 required => 1,
77 lazy => 1,
059c085b 78);
258733f1 79has _context => (
80 is => 'rw',
81 weak_ref => 1,
82 clearer => '_clear_context',
83);
fc7ec1d9 84
9ae060f0 85before [qw(status headers content_encoding content_length content_type header)] => sub {
86 my $self = shift;
87
2524941e 88 $self->_context->log->warn(
9ae060f0 89 "Useless setting a header value after finalize_headers called." .
90 " Not what you want." )
91 if ( $self->finalized_headers && @_ );
92};
93
059c085b 94sub output { shift->body(@_) }
95
aa9e8261 96sub code { shift->status(@_) }
97
9c4288ea 98sub write {
99 my ( $self, $buffer ) = @_;
100
101 # Finalize headers if someone manually writes output
89ba65d5 102 $self->_context->finalize_headers unless $self->finalized_headers;
9c4288ea 103
104 $buffer = q[] unless defined $buffer;
105
106 my $len = length($buffer);
107 $self->_writer->write($buffer);
108
109 return $len;
110}
111
9c4288ea 112sub finalize_headers {
113 my ($self) = @_;
9c4288ea 114 return;
115}
116
e67f0874 117sub from_psgi_response {
118 my ($self, $psgi_res) = @_;
119 if(ref $psgi_res eq 'ARRAY') {
120 my ($status, $headers, $body) = @$psgi_res;
121 $self->status($status);
4491e0cc 122 $self->headers(HTTP::Headers->new(@$headers));
8a3dcb98 123 $self->body($body);
e67f0874 124 } elsif(ref $psgi_res eq 'CODE') {
125 $psgi_res->(sub {
4491e0cc 126 my $response = shift;
127 my ($status, $headers, $maybe_body) = @$response;
e67f0874 128 $self->status($status);
4491e0cc 129 $self->headers(HTTP::Headers->new(@$headers));
8a3dcb98 130 if(defined $maybe_body) {
131 $self->body($maybe_body);
e67f0874 132 } else {
133 return $self->write_fh;
134 }
2524941e 135 });
4491e0cc 136 } else {
e67f0874 137 die "You can't set a Catalyst response from that, expect a valid PSGI response";
138 }
139}
140
fc7ec1d9 141=head1 NAME
142
910410b8 143Catalyst::Response - stores output responding to the current client request
fc7ec1d9 144
145=head1 SYNOPSIS
146
fbcc39ad 147 $res = $c->response;
148 $res->body;
aa9e8261 149 $res->code;
fbcc39ad 150 $res->content_encoding;
151 $res->content_length;
152 $res->content_type;
153 $res->cookies;
fbcc39ad 154 $res->header;
155 $res->headers;
156 $res->output;
157 $res->redirect;
158 $res->status;
159 $res->write;
b22c6668 160
fc7ec1d9 161=head1 DESCRIPTION
162
910410b8 163This is the Catalyst Response class, which provides methods for responding to
46372e65 164the current client request. The appropriate L<Catalyst::Engine> for your environment
165will turn the Catalyst::Response into a HTTP Response and return it to the client.
b22c6668 166
167=head1 METHODS
fc7ec1d9 168
08a2c908 169=head2 $res->body( $text | $fh | $iohandle_object )
e060fe05 170
171 $c->response->body('Catalyst rocks!');
06e1b616 172
46372e65 173Sets or returns the output (text or binary data). If you are returning a large body,
2f381252 174you might want to use a L<IO::Handle> type of object (Something that implements the read method
46372e65 175in the same fashion), or a filehandle GLOB. Catalyst
176will write it piece by piece into the response.
06e1b616 177
490b7a80 178When using a L<IO::Handle> type of object and no content length has been
179already set in the response headers Catalyst will make a reasonable attempt
180to determine the size of the Handle. Depending on the implementation of your
181handle object, setting the content length may fail. If it is at all possible
2524941e 182for you to determine the content length of your handle object,
4a178c0d 183it is recommended that you set the content length in the response headers
490b7a80 184yourself, which will be respected and sent by Catalyst in the response.
185
02570318 186=head2 $res->has_body
187
188Predicate which returns true when a body has been set.
189
aa9e8261 190=head2 $res->code
191
192Alias for $res->status.
193
b5ecfcf0 194=head2 $res->content_encoding
b5176d9e 195
910410b8 196Shortcut for $res->headers->content_encoding.
b5176d9e 197
b5ecfcf0 198=head2 $res->content_length
b5176d9e 199
910410b8 200Shortcut for $res->headers->content_length.
b5176d9e 201
b5ecfcf0 202=head2 $res->content_type
b5176d9e 203
910410b8 204Shortcut for $res->headers->content_type.
b5176d9e 205
87e9f9ab 206This value is typically set by your view or plugin. For example,
207L<Catalyst::Plugin::Static::Simple> will guess the mime type based on the file
208it found, while L<Catalyst::View::TT> defaults to C<text/html>.
209
b5ecfcf0 210=head2 $res->cookies
fc7ec1d9 211
910410b8 212Returns a reference to a hash containing cookies to be set. The keys of the
213hash are the cookies' names, and their corresponding values are hash
7e743798 214references used to construct a L<CGI::Simple::Cookie> object.
fc7ec1d9 215
216 $c->response->cookies->{foo} = { value => '123' };
217
7e743798 218The keys of the hash reference on the right correspond to the L<CGI::Simple::Cookie>
910410b8 219parameters of the same name, except they are used without a leading dash.
220Possible parameters are:
ac965e92 221
b0ad47c1 222=over
ac965e92 223
71453caf 224=item value
ac965e92 225
71453caf 226=item expires
ac965e92 227
71453caf 228=item domain
ac965e92 229
71453caf 230=item path
231
232=item secure
233
b21bc468 234=item httponly
235
71453caf 236=back
ac965e92 237
b5ecfcf0 238=head2 $res->header
fbcc39ad 239
910410b8 240Shortcut for $res->headers->header.
fbcc39ad 241
b5ecfcf0 242=head2 $res->headers
fc7ec1d9 243
910410b8 244Returns an L<HTTP::Headers> object, which can be used to set headers.
fc7ec1d9 245
246 $c->response->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
247
b5ecfcf0 248=head2 $res->output
fc7ec1d9 249
910410b8 250Alias for $res->body.
fc7ec1d9 251
b5ecfcf0 252=head2 $res->redirect( $url, $status )
fc7ec1d9 253
2f381252 254Causes the response to redirect to the specified URL. The default status is
255C<302>.
fc7ec1d9 256
73a52566 257 $c->response->redirect( 'http://slashdot.org' );
258 $c->response->redirect( 'http://slashdot.org', 307 );
259
2f381252 260This is a convenience method that sets the Location header to the
261redirect destination, and then sets the response status. You will
ee24f3a8 262want to C< return > or C<< $c->detach() >> to interrupt the normal
2f381252 263processing flow if you want the redirect to occur straight away.
264
824a5eb0 265B<Note:> do not give a relative URL as $url, i.e: one that is not fully
266qualified (= C<http://...>, etc.) or that starts with a slash
267(= C</path/here>). While it may work, it is not guaranteed to do the right
268thing and is not a standard behaviour. You may opt to use uri_for() or
269uri_for_action() instead.
270
73a52566 271=cut
272
273sub redirect {
274 my $self = shift;
fbcc39ad 275
276 if (@_) {
73a52566 277 my $location = shift;
f1bbebac 278 my $status = shift || 302;
73a52566 279
280 $self->location($location);
281 $self->status($status);
282 }
283
284 return $self->location;
285}
fc7ec1d9 286
2524941e 287around '_set_location' => sub {
288 my $orig = shift;
289 my $self = shift;
290
291 if (@_) {
292 my $location = shift;
293
294 if ( $location =~ m/[\n\r]/ ) { # check for header injection
295 die "blocking header injection";
296 } else {
297 $self->$orig($location);
298 }
299 } else {
300 $self->$orig();
301 }
302};
303
059c085b 304=head2 $res->location
305
306Sets or returns the HTTP 'Location'.
307
b5ecfcf0 308=head2 $res->status
fc7ec1d9 309
910410b8 310Sets or returns the HTTP status.
fc7ec1d9 311
312 $c->response->status(404);
aa9e8261 313
314$res->code is an alias for this, to match HTTP::Response->code.
b0ad47c1 315
b5ecfcf0 316=head2 $res->write( $data )
fbcc39ad 317
318Writes $data to the output stream.
319
e37f92f5 320=head2 $res->write_fh
321
322Returns a PSGI $writer object that has two methods, write and close. You can
323close over this object for asynchronous and nonblocking applications. For
324example (assuming you are using a supporting server, like L<Twiggy>
325
326 package AsyncExample::Controller::Root;
327
328 use Moose;
329
330 BEGIN { extends 'Catalyst::Controller' }
331
332 sub prepare_cb {
333 my $write_fh = pop;
334 return sub {
335 my $message = shift;
336 $write_fh->write("Finishing: $message\n");
337 $write_fh->close;
338 };
339 }
340
341 sub anyevent :Local :Args(0) {
342 my ($self, $c) = @_;
343 my $cb = $self->prepare_cb($c->res->write_fh);
344
345 my $watcher;
346 $watcher = AnyEvent->timer(
347 after => 5,
348 cb => sub {
349 $cb->(scalar localtime);
350 undef $watcher; # cancel circular-ref
351 });
352 }
353
e4cc83b2 354=head2 $res->print( @data )
355
356Prints @data to the output stream, separated by $,. This lets you pass
357the response object to functions that want to write to an L<IO::Handle>.
358
8738b8fe 359=head2 $self->finalize_headers($c)
360
361Writes headers to response if not already written
362
e67f0874 363=head2 from_psgi_response
364
365Given a PSGI response (either three element ARRAY reference OR coderef expecting
366a $responder) set the response from it.
367
368Properly supports streaming and delayed response and / or async IO if running
369under an expected event loop.
370
371Example:
372
373 package MyApp::Web::Controller::Test;
374
375 use base 'Catalyst::Controller';
376 use Plack::App::Directory;
377
378
379 my $app = Plack::App::Directory->new({ root => "/path/to/htdocs" })
380 ->to_app;
381
382 sub myaction :Local Args {
383 my ($self, $c) = @_;
faa1bcff 384 $c->res->from_psgi_response($app->($c->req->env));
e67f0874 385 }
386
387Please note this does not attempt to map or nest your PSGI application under
2524941e 388the Controller and Action namespace or path.
e67f0874 389
faa02805 390=head2 DEMOLISH
391
392Ensures that the response is flushed and closed at the end of the
393request.
394
395=head2 meta
396
397Provided by Moose
398
e4cc83b2 399=cut
400
401sub print {
402 my $self = shift;
403 my $data = shift;
404
405 defined $self->write($data) or return;
406
407 for (@_) {
408 defined $self->write($,) or return;
409 defined $self->write($_) or return;
410 }
fe3083a8 411 defined $self->write($\) or return;
b0ad47c1 412
e4cc83b2 413 return 1;
414}
415
910410b8 416=head1 AUTHORS
fc7ec1d9 417
2f381252 418Catalyst Contributors, see Catalyst.pm
fc7ec1d9 419
420=head1 COPYRIGHT
421
b0ad47c1 422This library is free software. You can redistribute it and/or modify
61b1e958 423it under the same terms as Perl itself.
fc7ec1d9 424
425=cut
426
e5ecd5bc 427__PACKAGE__->meta->make_immutable;
428
fc7ec1d9 4291;