merged and resolved conflicts from stable
[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';
e8361cf8 8use Catalyst::Response::Writer;
6adc45cf 9use Catalyst::Utils ();
fc7ec1d9 10
531f1ab6 11with 'MooseX::Emulate::Class::Accessor::Fast';
12
6adc45cf 13our $DEFAULT_ENCODE_CONTENT_TYPE_MATCH = qr{text|xml$|javascript$};
14
15has encodable_content_type => (
16 is => 'rw',
17 required => 1,
18 default => sub { $DEFAULT_ENCODE_CONTENT_TYPE_MATCH }
19);
20
faa02805 21has _response_cb => (
22 is => 'ro',
46fff667 23 isa => 'CodeRef',
faa02805 24 writer => '_set_response_cb',
25 clearer => '_clear_response_cb',
26 predicate => '_has_response_cb',
27);
28
29subtype 'Catalyst::Engine::Types::Writer',
30 as duck_type([qw(write close)]);
31
32has _writer => (
33 is => 'ro',
46fff667 34 isa => 'Catalyst::Engine::Types::Writer', #Pointless since we control how this is built
35 #writer => '_set_writer', Now that its lazy I think this is safe to remove
faa02805 36 clearer => '_clear_writer',
37 predicate => '_has_writer',
46fff667 38 lazy => 1,
39 builder => '_build_writer',
faa02805 40);
41
46fff667 42sub _build_writer {
43 my $self = shift;
44
45 ## These two lines are probably crap now...
46 $self->_context->finalize_headers unless
47 $self->finalized_headers;
48
49 my @headers;
50 $self->headers->scan(sub { push @headers, @_ });
51
52 my $writer = $self->_response_cb->([ $self->status, \@headers ]);
53 $self->_clear_response_cb;
54
55 return $writer;
56}
57
e37f92f5 58has write_fh => (
59 is=>'ro',
a3c9ab76 60 predicate=>'_has_write_fh',
eb1f4b49 61 lazy=>1,
1f2a8069 62 builder=>'_build_write_fh',
63);
64
e8361cf8 65sub _build_write_fh {
66 my $writer = $_[0]->_writer; # We need to get the finalize headers side effect...
6adc45cf 67 my $requires_encoding = $_[0]->encodable_response;
e8361cf8 68 my %fields = (
69 _writer => $writer,
6adc45cf 70 _encoding => $_[0]->_context->encoding,
e8361cf8 71 _requires_encoding => $requires_encoding,
72 );
73
74 return bless \%fields, 'Catalyst::Response::Writer';
75}
e37f92f5 76
77sub DEMOLISH {
78 my $self = shift;
a3c9ab76 79 return if $self->_has_write_fh;
e37f92f5 80 if($self->_has_writer) {
81 $self->_writer->close
82 }
83}
faa02805 84
6680c772 85has cookies => (is => 'rw', default => sub { {} });
ffb43803 86has body => (is => 'rw', default => undef);
87sub has_body { defined($_[0]->body) }
99a543ee 88
059c085b 89has location => (is => 'rw');
6680c772 90has status => (is => 'rw', default => 200);
91has finalized_headers => (is => 'rw', default => 0);
059c085b 92has headers => (
93 is => 'rw',
9c331634 94 isa => 'HTTP::Headers',
6adc45cf 95 handles => [qw(content_encoding content_length content_type content_type_charset header)],
6680c772 96 default => sub { HTTP::Headers->new() },
97 required => 1,
98 lazy => 1,
059c085b 99);
258733f1 100has _context => (
101 is => 'rw',
102 weak_ref => 1,
103 clearer => '_clear_context',
104);
fc7ec1d9 105
9ae060f0 106before [qw(status headers content_encoding content_length content_type header)] => sub {
107 my $self = shift;
108
109 $self->_context->log->warn(
6adc45cf 110 "Useless setting a header value after finalize_headers and the response callback has been called." .
9ae060f0 111 " Not what you want." )
6adc45cf 112 if ( $self->finalized_headers && !$self->_has_response_cb && @_ );
9ae060f0 113};
114
059c085b 115sub output { shift->body(@_) }
116
aa9e8261 117sub code { shift->status(@_) }
118
9c4288ea 119sub write {
120 my ( $self, $buffer ) = @_;
121
122 # Finalize headers if someone manually writes output
89ba65d5 123 $self->_context->finalize_headers unless $self->finalized_headers;
9c4288ea 124
125 $buffer = q[] unless defined $buffer;
5c397774 126
6adc45cf 127 if($self->encodable_response) {
128 $buffer = $self->_context->encoding->encode( $buffer, $self->_context->_encode_check )
129 }
9c4288ea 130
131 my $len = length($buffer);
132 $self->_writer->write($buffer);
133
134 return $len;
135}
136
9c4288ea 137sub finalize_headers {
138 my ($self) = @_;
9c4288ea 139 return;
140}
141
e67f0874 142sub from_psgi_response {
143 my ($self, $psgi_res) = @_;
b194746d 144 if(blessed($psgi_res) && $psgi_res->can('as_psgi')) {
145 $psgi_res = $psgi_res->as_psgi;
146 }
e67f0874 147 if(ref $psgi_res eq 'ARRAY') {
148 my ($status, $headers, $body) = @$psgi_res;
149 $self->status($status);
4491e0cc 150 $self->headers(HTTP::Headers->new(@$headers));
8a3dcb98 151 $self->body($body);
e67f0874 152 } elsif(ref $psgi_res eq 'CODE') {
153 $psgi_res->(sub {
4491e0cc 154 my $response = shift;
155 my ($status, $headers, $maybe_body) = @$response;
e67f0874 156 $self->status($status);
4491e0cc 157 $self->headers(HTTP::Headers->new(@$headers));
8a3dcb98 158 if(defined $maybe_body) {
159 $self->body($maybe_body);
e67f0874 160 } else {
161 return $self->write_fh;
162 }
4491e0cc 163 });
164 } else {
e67f0874 165 die "You can't set a Catalyst response from that, expect a valid PSGI response";
166 }
167}
168
fc7ec1d9 169=head1 NAME
170
910410b8 171Catalyst::Response - stores output responding to the current client request
fc7ec1d9 172
173=head1 SYNOPSIS
174
fbcc39ad 175 $res = $c->response;
176 $res->body;
aa9e8261 177 $res->code;
fbcc39ad 178 $res->content_encoding;
179 $res->content_length;
180 $res->content_type;
181 $res->cookies;
fbcc39ad 182 $res->header;
183 $res->headers;
184 $res->output;
185 $res->redirect;
186 $res->status;
187 $res->write;
b22c6668 188
fc7ec1d9 189=head1 DESCRIPTION
190
910410b8 191This is the Catalyst Response class, which provides methods for responding to
46372e65 192the current client request. The appropriate L<Catalyst::Engine> for your environment
193will turn the Catalyst::Response into a HTTP Response and return it to the client.
b22c6668 194
195=head1 METHODS
fc7ec1d9 196
08a2c908 197=head2 $res->body( $text | $fh | $iohandle_object )
e060fe05 198
199 $c->response->body('Catalyst rocks!');
06e1b616 200
46372e65 201Sets or returns the output (text or binary data). If you are returning a large body,
2f381252 202you might want to use a L<IO::Handle> type of object (Something that implements the read method
46372e65 203in the same fashion), or a filehandle GLOB. Catalyst
204will write it piece by piece into the response.
06e1b616 205
6adc45cf 206If you are using a filehandle as the body response you are responsible for
207making sure it comforms to the L<PSGI> specification with regards to content
208encoding. Unlike with scalar body values or when using the streaming interfaces
209we currently do not attempt to normalize and encode your filehandle. In general
210this means you should be sure to be sending bytes not UTF8 decoded multibyte
211characters.
212
213Most of the time when you do:
214
215 open(my $fh, '<:raw', $path);
216
217You should be fine. If you open a filehandle with a L<PerlIO> layer you probably
218are not fine. You can usually fix this by explicitly using binmode to set
219the IOLayer to :raw. Its possible future versions of L<Catalyst> will try to
220'do the right thing'.
221
490b7a80 222When using a L<IO::Handle> type of object and no content length has been
223already set in the response headers Catalyst will make a reasonable attempt
224to determine the size of the Handle. Depending on the implementation of your
225handle object, setting the content length may fail. If it is at all possible
226for you to determine the content length of your handle object,
4a178c0d 227it is recommended that you set the content length in the response headers
490b7a80 228yourself, which will be respected and sent by Catalyst in the response.
229
efeeb257 230Please note that the object needs to implement C<getline>, not just
231C<read>.
232
233Starting from version 5.90060, when using an L<IO::Handle> object, you
234may want to use L<Plack::Middleware::XSendfile>, to delegate the
235actual serving to the frontend server. To do so, you need to pass to
236C<body> an IO object with a C<path> method. This can be achieved in
237two ways.
238
239Either using L<Plack::Util>:
240
241 my $fh = IO::File->new($file, 'r');
242 Plack::Util::set_io_path($fh, $file);
243
244Or using L<IO::File::WithPath>
245
246 my $fh = IO::File::WithPath->new($file, 'r');
247
248And then passing the filehandle to body and setting headers, if needed.
249
250 $c->response->body($fh);
251 $c->response->headers->content_type('text/plain');
252 $c->response->headers->content_length(-s $file);
253 $c->response->headers->last_modified((stat($file))[9]);
254
255L<Plack::Middleware::XSendfile> can be loaded in the application so:
256
257 __PACKAGE__->config(
258 psgi_middleware => [
259 'XSendfile',
260 # other middlewares here...
261 ],
262 );
263
264B<Beware> that loading the middleware without configuring the
265webserver to set the request header C<X-Sendfile-Type> to a supported
266type (C<X-Accel-Redirect> for nginx, C<X-Sendfile> for Apache and
267Lighttpd), could lead to the disclosure of private paths to malicious
268clients setting that header.
269
270Nginx needs the additional X-Accel-Mapping header to be set in the
271webserver configuration, so the middleware will replace the absolute
272path of the IO object with the internal nginx path. This is also
273useful to prevent a buggy app to server random files from the
274filesystem, as it's an internal redirect.
275
276An nginx configuration for FastCGI could look so:
277
278 server {
279 server_name example.com;
280 root /my/app/root;
281 location /private/repo/ {
282 internal;
283 alias /my/app/repo/;
284 }
285 location /private/staging/ {
286 internal;
287 alias /my/app/staging/;
288 }
289 location @proxy {
290 include /etc/nginx/fastcgi_params;
291 fastcgi_param SCRIPT_NAME '';
292 fastcgi_param PATH_INFO $fastcgi_script_name;
293 fastcgi_param HTTP_X_SENDFILE_TYPE X-Accel-Redirect;
294 fastcgi_param HTTP_X_ACCEL_MAPPING /my/app=/private;
295 fastcgi_pass unix:/my/app/run/app.sock;
296 }
297 }
298
299In the example above, passing filehandles with a local path matching
300/my/app/staging or /my/app/repo will be served by nginx. Passing paths
301with other locations will lead to an internal server error.
302
303Setting the body to a filehandle without the C<path> method bypasses
304the middleware completely.
305
306For Apache and Lighttpd, the mapping doesn't apply and setting the
307X-Sendfile-Type is enough.
308
02570318 309=head2 $res->has_body
310
311Predicate which returns true when a body has been set.
312
aa9e8261 313=head2 $res->code
314
315Alias for $res->status.
316
b5ecfcf0 317=head2 $res->content_encoding
b5176d9e 318
910410b8 319Shortcut for $res->headers->content_encoding.
b5176d9e 320
b5ecfcf0 321=head2 $res->content_length
b5176d9e 322
910410b8 323Shortcut for $res->headers->content_length.
b5176d9e 324
b5ecfcf0 325=head2 $res->content_type
b5176d9e 326
910410b8 327Shortcut for $res->headers->content_type.
b5176d9e 328
87e9f9ab 329This value is typically set by your view or plugin. For example,
330L<Catalyst::Plugin::Static::Simple> will guess the mime type based on the file
331it found, while L<Catalyst::View::TT> defaults to C<text/html>.
332
6adc45cf 333=head2 $res->content_type_charset
334
335Shortcut for $res->headers->content_type_charset;
336
b5ecfcf0 337=head2 $res->cookies
fc7ec1d9 338
910410b8 339Returns a reference to a hash containing cookies to be set. The keys of the
340hash are the cookies' names, and their corresponding values are hash
7e743798 341references used to construct a L<CGI::Simple::Cookie> object.
fc7ec1d9 342
343 $c->response->cookies->{foo} = { value => '123' };
344
7e743798 345The keys of the hash reference on the right correspond to the L<CGI::Simple::Cookie>
910410b8 346parameters of the same name, except they are used without a leading dash.
347Possible parameters are:
ac965e92 348
b0ad47c1 349=over
ac965e92 350
71453caf 351=item value
ac965e92 352
71453caf 353=item expires
ac965e92 354
71453caf 355=item domain
ac965e92 356
71453caf 357=item path
358
359=item secure
360
b21bc468 361=item httponly
362
71453caf 363=back
ac965e92 364
b5ecfcf0 365=head2 $res->header
fbcc39ad 366
910410b8 367Shortcut for $res->headers->header.
fbcc39ad 368
b5ecfcf0 369=head2 $res->headers
fc7ec1d9 370
910410b8 371Returns an L<HTTP::Headers> object, which can be used to set headers.
fc7ec1d9 372
373 $c->response->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
374
b5ecfcf0 375=head2 $res->output
fc7ec1d9 376
910410b8 377Alias for $res->body.
fc7ec1d9 378
b5ecfcf0 379=head2 $res->redirect( $url, $status )
fc7ec1d9 380
2f381252 381Causes the response to redirect to the specified URL. The default status is
382C<302>.
fc7ec1d9 383
73a52566 384 $c->response->redirect( 'http://slashdot.org' );
385 $c->response->redirect( 'http://slashdot.org', 307 );
386
2f381252 387This is a convenience method that sets the Location header to the
388redirect destination, and then sets the response status. You will
ee24f3a8 389want to C< return > or C<< $c->detach() >> to interrupt the normal
2f381252 390processing flow if you want the redirect to occur straight away.
391
824a5eb0 392B<Note:> do not give a relative URL as $url, i.e: one that is not fully
393qualified (= C<http://...>, etc.) or that starts with a slash
394(= C</path/here>). While it may work, it is not guaranteed to do the right
395thing and is not a standard behaviour. You may opt to use uri_for() or
396uri_for_action() instead.
397
00038a21 398B<Note:> If $url is an object that does ->as_string (such as L<URI>, which is
399what you get from ->uri_for) we automatically call that to stringify. This
400should ease the common case usage
401
402 return $c->res->redirect( $c->uri_for(...));
403
73a52566 404=cut
405
406sub redirect {
407 my $self = shift;
fbcc39ad 408
409 if (@_) {
73a52566 410 my $location = shift;
f1bbebac 411 my $status = shift || 302;
73a52566 412
00038a21 413 if(blessed($location) && $location->can('as_string')) {
414 $location = $location->as_string;
415 }
416
73a52566 417 $self->location($location);
418 $self->status($status);
419 }
420
421 return $self->location;
422}
fc7ec1d9 423
059c085b 424=head2 $res->location
425
426Sets or returns the HTTP 'Location'.
427
b5ecfcf0 428=head2 $res->status
fc7ec1d9 429
910410b8 430Sets or returns the HTTP status.
fc7ec1d9 431
432 $c->response->status(404);
aa9e8261 433
434$res->code is an alias for this, to match HTTP::Response->code.
b0ad47c1 435
b5ecfcf0 436=head2 $res->write( $data )
fbcc39ad 437
dd096a3a 438Writes $data to the output stream. Calling this method will finalize your
439headers and send the headers and status code response to the client (so changing
440them afterwards is a waste... be sure to set your headers correctly first).
441
442You may call this as often as you want throughout your response cycle. You may
443even set a 'body' afterward. So for example you might write your HTTP headers
444and the HEAD section of your document and then set the body from a template
445driven from a database. In some cases this can seem to the client as if you had
446a faster overall response (but note that unless your server support chunked
447body your content is likely to get queued anyway (L<Starman> and most other
448http 1.1 webservers support this).
449
450If there is an encoding set, we encode each line of the response (the default
451encoding is UTF-8).
fbcc39ad 452
e37f92f5 453=head2 $res->write_fh
454
e8361cf8 455Returns an instance of L<Catalyst::Response::Writer>, which is a lightweight
456decorator over the PSGI C<$writer> object (see L<PSGI.pod\Delayed-Response-and-Streaming-Body>).
457
458In addition to proxying the C<write> and C<close> method from the underlying PSGI
459writer, this proxy object knows any application wide encoding, and provides a method
460C<write_encoded> that will properly encode your written lines based upon your
461encoding settings. By default in L<Catalyst> responses are UTF-8 encoded and this
462is the encoding used if you respond via C<write_encoded>. If you want to handle
463encoding yourself, you can use the C<write> method directly.
464
465Encoding only applies to content types for which it matters. Currently the following
466content types are assumed to need encoding: text (including HTML), xml and javascript.
467
468We provide access to this object so that you can properly close over it for use in
469asynchronous and nonblocking applications. For example (assuming you are using a supporting
470server, like L<Twiggy>:
e37f92f5 471
472 package AsyncExample::Controller::Root;
473
474 use Moose;
475
476 BEGIN { extends 'Catalyst::Controller' }
477
478 sub prepare_cb {
479 my $write_fh = pop;
480 return sub {
481 my $message = shift;
482 $write_fh->write("Finishing: $message\n");
483 $write_fh->close;
484 };
485 }
486
487 sub anyevent :Local :Args(0) {
488 my ($self, $c) = @_;
489 my $cb = $self->prepare_cb($c->res->write_fh);
490
491 my $watcher;
492 $watcher = AnyEvent->timer(
493 after => 5,
494 cb => sub {
495 $cb->(scalar localtime);
496 undef $watcher; # cancel circular-ref
497 });
498 }
499
dd096a3a 500Like the 'write' method, calling this will finalize headers. Unlike 'write' when you
501can this it is assumed you are taking control of the response so the body is never
502finalized (there isn't one anyway) and you need to call the close method.
503
e4cc83b2 504=head2 $res->print( @data )
505
506Prints @data to the output stream, separated by $,. This lets you pass
507the response object to functions that want to write to an L<IO::Handle>.
508
8738b8fe 509=head2 $self->finalize_headers($c)
510
511Writes headers to response if not already written
512
e67f0874 513=head2 from_psgi_response
514
515Given a PSGI response (either three element ARRAY reference OR coderef expecting
516a $responder) set the response from it.
517
518Properly supports streaming and delayed response and / or async IO if running
519under an expected event loop.
520
b194746d 521If passed an object, will expect that object to do a method C<as_psgi>.
522
e67f0874 523Example:
524
525 package MyApp::Web::Controller::Test;
526
527 use base 'Catalyst::Controller';
528 use Plack::App::Directory;
529
530
531 my $app = Plack::App::Directory->new({ root => "/path/to/htdocs" })
532 ->to_app;
533
534 sub myaction :Local Args {
535 my ($self, $c) = @_;
faa1bcff 536 $c->res->from_psgi_response($app->($c->req->env));
e67f0874 537 }
538
539Please note this does not attempt to map or nest your PSGI application under
540the Controller and Action namespace or path.
541
6adc45cf 542=head2 encodable_content_type
543
544This is a regular expression used to determine of the current content type
545should be considered encodable. Currently we apply default encoding (usually
546UTF8) to text type contents. Here's the default regular expression:
547
548This would match content types like:
549
550 text/plain
551 text/html
552 text/xml
553 application/javascript
554 application/xml
555 application/vnd.user+xml
556
557B<NOTE>: We don't encode JSON content type responses by default since most
558of the JSON serializers that are commonly used for this task will do so
559automatically and we don't want to double encode. If you are not using a
560tool like L<JSON> to produce JSON type content, (for example you are using
561a template system, or creating the strings manually) you will need to either
562encoding the body yourself:
563
564 $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) );
565
566Or you can alter the regular expression using this attribute.
567
568=head2 encodable_response
569
570Given a L<Catalyst::Response> return true if its one that can be encoded.
571
572 make sure there is an encoding set on the response
573 make sure the content type is encodable
574 make sure no content type charset has been already set to something different from the global encoding
575 make sure no content encoding is present.
576
577Note this does not inspect a body since we do allow automatic encoding on streaming
578type responses.
579
580=cut
581
582sub encodable_response {
583 my ($self) = @_;
584 return 0 unless $self->_context; # Cases like returning a HTTP Exception response you don't have a context here...
585 return 0 unless $self->_context->encoding;
586
587 my $has_manual_charset = 0;
588 if(my $charset = $self->content_type_charset) {
589 $has_manual_charset = (uc($charset) ne uc($self->_context->encoding->mime_name)) ? 1:0;
590 }
591
592 if(
593 ($self->content_type =~ m/${\$self->encodable_content_type}/) and
594 (!$has_manual_charset) and
595 (!$self->content_encoding || $self->content_encoding eq 'identity' )
596 ) {
597 return 1;
598 } else {
599 return 0;
600 }
601}
602
faa02805 603=head2 DEMOLISH
604
605Ensures that the response is flushed and closed at the end of the
606request.
607
608=head2 meta
609
610Provided by Moose
611
e4cc83b2 612=cut
613
614sub print {
615 my $self = shift;
616 my $data = shift;
617
618 defined $self->write($data) or return;
619
620 for (@_) {
621 defined $self->write($,) or return;
622 defined $self->write($_) or return;
623 }
fe3083a8 624 defined $self->write($\) or return;
b0ad47c1 625
e4cc83b2 626 return 1;
627}
628
910410b8 629=head1 AUTHORS
fc7ec1d9 630
2f381252 631Catalyst Contributors, see Catalyst.pm
fc7ec1d9 632
633=head1 COPYRIGHT
634
b0ad47c1 635This library is free software. You can redistribute it and/or modify
61b1e958 636it under the same terms as Perl itself.
fc7ec1d9 637
638=cut
639
e5ecd5bc 640__PACKAGE__->meta->make_immutable;
641
fc7ec1d9 6421;