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