added links to UTF8 docs in delta and upgrading
[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,
688e2420 70 _context => $_[0]->_context,
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,
77b5811a 202you might want to use a L<IO::Handle> type of object (Something that implements the getline method
203in the same fashion), or a filehandle GLOB. These will be passed down to the PSGI
204handler you are using and might be optimized using server specific abilities (for
205example L<Twiggy> will attempt to server a real local file in a non blocking manner).
06e1b616 206
6adc45cf 207If you are using a filehandle as the body response you are responsible for
566678d0 208making sure it conforms to the L<PSGI> specification with regards to content
6adc45cf 209encoding. Unlike with scalar body values or when using the streaming interfaces
210we currently do not attempt to normalize and encode your filehandle. In general
211this means you should be sure to be sending bytes not UTF8 decoded multibyte
212characters.
213
214Most of the time when you do:
215
216 open(my $fh, '<:raw', $path);
217
218You should be fine. If you open a filehandle with a L<PerlIO> layer you probably
219are not fine. You can usually fix this by explicitly using binmode to set
220the IOLayer to :raw. Its possible future versions of L<Catalyst> will try to
221'do the right thing'.
222
490b7a80 223When using a L<IO::Handle> type of object and no content length has been
224already set in the response headers Catalyst will make a reasonable attempt
225to determine the size of the Handle. Depending on the implementation of your
226handle object, setting the content length may fail. If it is at all possible
227for you to determine the content length of your handle object,
4a178c0d 228it is recommended that you set the content length in the response headers
490b7a80 229yourself, which will be respected and sent by Catalyst in the response.
230
efeeb257 231Please note that the object needs to implement C<getline>, not just
77b5811a 232C<read>. Older versions of L<Catalyst> expected your filehandle like objects
233to do read. If you have code written for this expectation and you cannot
234change the code to meet the L<PSGI> specification, you can try the following
235middleware L<Plack::Middleware::AdaptFilehandleRead> which will attempt to
236wrap your object in an interface that so conforms.
efeeb257 237
238Starting from version 5.90060, when using an L<IO::Handle> object, you
239may want to use L<Plack::Middleware::XSendfile>, to delegate the
240actual serving to the frontend server. To do so, you need to pass to
241C<body> an IO object with a C<path> method. This can be achieved in
242two ways.
243
244Either using L<Plack::Util>:
245
246 my $fh = IO::File->new($file, 'r');
247 Plack::Util::set_io_path($fh, $file);
248
249Or using L<IO::File::WithPath>
250
251 my $fh = IO::File::WithPath->new($file, 'r');
252
253And then passing the filehandle to body and setting headers, if needed.
254
255 $c->response->body($fh);
256 $c->response->headers->content_type('text/plain');
257 $c->response->headers->content_length(-s $file);
258 $c->response->headers->last_modified((stat($file))[9]);
259
260L<Plack::Middleware::XSendfile> can be loaded in the application so:
261
262 __PACKAGE__->config(
263 psgi_middleware => [
264 'XSendfile',
265 # other middlewares here...
266 ],
267 );
268
269B<Beware> that loading the middleware without configuring the
270webserver to set the request header C<X-Sendfile-Type> to a supported
271type (C<X-Accel-Redirect> for nginx, C<X-Sendfile> for Apache and
272Lighttpd), could lead to the disclosure of private paths to malicious
273clients setting that header.
274
275Nginx needs the additional X-Accel-Mapping header to be set in the
276webserver configuration, so the middleware will replace the absolute
277path of the IO object with the internal nginx path. This is also
278useful to prevent a buggy app to server random files from the
279filesystem, as it's an internal redirect.
280
281An nginx configuration for FastCGI could look so:
282
283 server {
284 server_name example.com;
285 root /my/app/root;
286 location /private/repo/ {
287 internal;
288 alias /my/app/repo/;
289 }
290 location /private/staging/ {
291 internal;
292 alias /my/app/staging/;
293 }
294 location @proxy {
295 include /etc/nginx/fastcgi_params;
296 fastcgi_param SCRIPT_NAME '';
297 fastcgi_param PATH_INFO $fastcgi_script_name;
298 fastcgi_param HTTP_X_SENDFILE_TYPE X-Accel-Redirect;
299 fastcgi_param HTTP_X_ACCEL_MAPPING /my/app=/private;
300 fastcgi_pass unix:/my/app/run/app.sock;
301 }
302 }
303
304In the example above, passing filehandles with a local path matching
305/my/app/staging or /my/app/repo will be served by nginx. Passing paths
306with other locations will lead to an internal server error.
307
308Setting the body to a filehandle without the C<path> method bypasses
309the middleware completely.
310
311For Apache and Lighttpd, the mapping doesn't apply and setting the
312X-Sendfile-Type is enough.
313
02570318 314=head2 $res->has_body
315
316Predicate which returns true when a body has been set.
317
aa9e8261 318=head2 $res->code
319
320Alias for $res->status.
321
b5ecfcf0 322=head2 $res->content_encoding
b5176d9e 323
910410b8 324Shortcut for $res->headers->content_encoding.
b5176d9e 325
b5ecfcf0 326=head2 $res->content_length
b5176d9e 327
910410b8 328Shortcut for $res->headers->content_length.
b5176d9e 329
b5ecfcf0 330=head2 $res->content_type
b5176d9e 331
910410b8 332Shortcut for $res->headers->content_type.
b5176d9e 333
87e9f9ab 334This value is typically set by your view or plugin. For example,
335L<Catalyst::Plugin::Static::Simple> will guess the mime type based on the file
336it found, while L<Catalyst::View::TT> defaults to C<text/html>.
337
6adc45cf 338=head2 $res->content_type_charset
339
340Shortcut for $res->headers->content_type_charset;
341
b5ecfcf0 342=head2 $res->cookies
fc7ec1d9 343
910410b8 344Returns a reference to a hash containing cookies to be set. The keys of the
345hash are the cookies' names, and their corresponding values are hash
7e743798 346references used to construct a L<CGI::Simple::Cookie> object.
fc7ec1d9 347
348 $c->response->cookies->{foo} = { value => '123' };
349
7e743798 350The keys of the hash reference on the right correspond to the L<CGI::Simple::Cookie>
910410b8 351parameters of the same name, except they are used without a leading dash.
352Possible parameters are:
ac965e92 353
b0ad47c1 354=over
ac965e92 355
71453caf 356=item value
ac965e92 357
71453caf 358=item expires
ac965e92 359
71453caf 360=item domain
ac965e92 361
71453caf 362=item path
363
364=item secure
365
b21bc468 366=item httponly
367
71453caf 368=back
ac965e92 369
b5ecfcf0 370=head2 $res->header
fbcc39ad 371
910410b8 372Shortcut for $res->headers->header.
fbcc39ad 373
b5ecfcf0 374=head2 $res->headers
fc7ec1d9 375
910410b8 376Returns an L<HTTP::Headers> object, which can be used to set headers.
fc7ec1d9 377
378 $c->response->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
379
b5ecfcf0 380=head2 $res->output
fc7ec1d9 381
910410b8 382Alias for $res->body.
fc7ec1d9 383
b5ecfcf0 384=head2 $res->redirect( $url, $status )
fc7ec1d9 385
2f381252 386Causes the response to redirect to the specified URL. The default status is
387C<302>.
fc7ec1d9 388
73a52566 389 $c->response->redirect( 'http://slashdot.org' );
390 $c->response->redirect( 'http://slashdot.org', 307 );
391
2f381252 392This is a convenience method that sets the Location header to the
393redirect destination, and then sets the response status. You will
ee24f3a8 394want to C< return > or C<< $c->detach() >> to interrupt the normal
2f381252 395processing flow if you want the redirect to occur straight away.
396
824a5eb0 397B<Note:> do not give a relative URL as $url, i.e: one that is not fully
398qualified (= C<http://...>, etc.) or that starts with a slash
399(= C</path/here>). While it may work, it is not guaranteed to do the right
400thing and is not a standard behaviour. You may opt to use uri_for() or
401uri_for_action() instead.
402
00038a21 403B<Note:> If $url is an object that does ->as_string (such as L<URI>, which is
404what you get from ->uri_for) we automatically call that to stringify. This
405should ease the common case usage
406
407 return $c->res->redirect( $c->uri_for(...));
408
73a52566 409=cut
410
411sub redirect {
412 my $self = shift;
fbcc39ad 413
414 if (@_) {
73a52566 415 my $location = shift;
f1bbebac 416 my $status = shift || 302;
73a52566 417
00038a21 418 if(blessed($location) && $location->can('as_string')) {
419 $location = $location->as_string;
420 }
421
73a52566 422 $self->location($location);
423 $self->status($status);
424 }
425
426 return $self->location;
427}
fc7ec1d9 428
059c085b 429=head2 $res->location
430
431Sets or returns the HTTP 'Location'.
432
b5ecfcf0 433=head2 $res->status
fc7ec1d9 434
910410b8 435Sets or returns the HTTP status.
fc7ec1d9 436
437 $c->response->status(404);
aa9e8261 438
439$res->code is an alias for this, to match HTTP::Response->code.
b0ad47c1 440
b5ecfcf0 441=head2 $res->write( $data )
fbcc39ad 442
dd096a3a 443Writes $data to the output stream. Calling this method will finalize your
444headers and send the headers and status code response to the client (so changing
445them afterwards is a waste... be sure to set your headers correctly first).
446
447You may call this as often as you want throughout your response cycle. You may
448even set a 'body' afterward. So for example you might write your HTTP headers
449and the HEAD section of your document and then set the body from a template
450driven from a database. In some cases this can seem to the client as if you had
451a faster overall response (but note that unless your server support chunked
452body your content is likely to get queued anyway (L<Starman> and most other
453http 1.1 webservers support this).
454
455If there is an encoding set, we encode each line of the response (the default
456encoding is UTF-8).
fbcc39ad 457
e37f92f5 458=head2 $res->write_fh
459
e8361cf8 460Returns an instance of L<Catalyst::Response::Writer>, which is a lightweight
461decorator over the PSGI C<$writer> object (see L<PSGI.pod\Delayed-Response-and-Streaming-Body>).
462
463In addition to proxying the C<write> and C<close> method from the underlying PSGI
464writer, this proxy object knows any application wide encoding, and provides a method
465C<write_encoded> that will properly encode your written lines based upon your
466encoding settings. By default in L<Catalyst> responses are UTF-8 encoded and this
467is the encoding used if you respond via C<write_encoded>. If you want to handle
468encoding yourself, you can use the C<write> method directly.
469
470Encoding only applies to content types for which it matters. Currently the following
471content types are assumed to need encoding: text (including HTML), xml and javascript.
472
473We provide access to this object so that you can properly close over it for use in
474asynchronous and nonblocking applications. For example (assuming you are using a supporting
475server, like L<Twiggy>:
e37f92f5 476
477 package AsyncExample::Controller::Root;
478
479 use Moose;
480
481 BEGIN { extends 'Catalyst::Controller' }
482
483 sub prepare_cb {
484 my $write_fh = pop;
485 return sub {
486 my $message = shift;
487 $write_fh->write("Finishing: $message\n");
488 $write_fh->close;
489 };
490 }
491
492 sub anyevent :Local :Args(0) {
493 my ($self, $c) = @_;
494 my $cb = $self->prepare_cb($c->res->write_fh);
495
496 my $watcher;
497 $watcher = AnyEvent->timer(
498 after => 5,
499 cb => sub {
500 $cb->(scalar localtime);
501 undef $watcher; # cancel circular-ref
502 });
503 }
504
dd096a3a 505Like the 'write' method, calling this will finalize headers. Unlike 'write' when you
506can this it is assumed you are taking control of the response so the body is never
507finalized (there isn't one anyway) and you need to call the close method.
508
e4cc83b2 509=head2 $res->print( @data )
510
511Prints @data to the output stream, separated by $,. This lets you pass
512the response object to functions that want to write to an L<IO::Handle>.
513
8738b8fe 514=head2 $self->finalize_headers($c)
515
516Writes headers to response if not already written
517
e67f0874 518=head2 from_psgi_response
519
520Given a PSGI response (either three element ARRAY reference OR coderef expecting
521a $responder) set the response from it.
522
523Properly supports streaming and delayed response and / or async IO if running
524under an expected event loop.
525
b194746d 526If passed an object, will expect that object to do a method C<as_psgi>.
527
e67f0874 528Example:
529
530 package MyApp::Web::Controller::Test;
531
532 use base 'Catalyst::Controller';
533 use Plack::App::Directory;
534
535
536 my $app = Plack::App::Directory->new({ root => "/path/to/htdocs" })
537 ->to_app;
538
539 sub myaction :Local Args {
540 my ($self, $c) = @_;
faa1bcff 541 $c->res->from_psgi_response($app->($c->req->env));
e67f0874 542 }
543
544Please note this does not attempt to map or nest your PSGI application under
545the Controller and Action namespace or path.
546
6adc45cf 547=head2 encodable_content_type
548
549This is a regular expression used to determine of the current content type
550should be considered encodable. Currently we apply default encoding (usually
551UTF8) to text type contents. Here's the default regular expression:
552
553This would match content types like:
554
555 text/plain
556 text/html
557 text/xml
558 application/javascript
559 application/xml
560 application/vnd.user+xml
561
562B<NOTE>: We don't encode JSON content type responses by default since most
563of the JSON serializers that are commonly used for this task will do so
564automatically and we don't want to double encode. If you are not using a
565tool like L<JSON> to produce JSON type content, (for example you are using
566a template system, or creating the strings manually) you will need to either
567encoding the body yourself:
568
569 $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) );
570
571Or you can alter the regular expression using this attribute.
572
573=head2 encodable_response
574
575Given a L<Catalyst::Response> return true if its one that can be encoded.
576
577 make sure there is an encoding set on the response
578 make sure the content type is encodable
579 make sure no content type charset has been already set to something different from the global encoding
580 make sure no content encoding is present.
581
582Note this does not inspect a body since we do allow automatic encoding on streaming
583type responses.
584
585=cut
586
587sub encodable_response {
588 my ($self) = @_;
589 return 0 unless $self->_context; # Cases like returning a HTTP Exception response you don't have a context here...
590 return 0 unless $self->_context->encoding;
591
592 my $has_manual_charset = 0;
593 if(my $charset = $self->content_type_charset) {
594 $has_manual_charset = (uc($charset) ne uc($self->_context->encoding->mime_name)) ? 1:0;
595 }
596
597 if(
598 ($self->content_type =~ m/${\$self->encodable_content_type}/) and
599 (!$has_manual_charset) and
600 (!$self->content_encoding || $self->content_encoding eq 'identity' )
601 ) {
602 return 1;
603 } else {
604 return 0;
605 }
606}
607
faa02805 608=head2 DEMOLISH
609
610Ensures that the response is flushed and closed at the end of the
611request.
612
613=head2 meta
614
615Provided by Moose
616
e4cc83b2 617=cut
618
619sub print {
620 my $self = shift;
621 my $data = shift;
622
623 defined $self->write($data) or return;
624
625 for (@_) {
626 defined $self->write($,) or return;
627 defined $self->write($_) or return;
628 }
fe3083a8 629 defined $self->write($\) or return;
b0ad47c1 630
e4cc83b2 631 return 1;
632}
633
910410b8 634=head1 AUTHORS
fc7ec1d9 635
2f381252 636Catalyst Contributors, see Catalyst.pm
fc7ec1d9 637
638=head1 COPYRIGHT
639
b0ad47c1 640This library is free software. You can redistribute it and/or modify
61b1e958 641it under the same terms as Perl itself.
fc7ec1d9 642
643=cut
644
e5ecd5bc 645__PACKAGE__->meta->make_immutable;
646
fc7ec1d9 6471;