donot encode write unless the content type is one of the encodable types
[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;
5c397774 106
107 $buffer = $self->_context->encoding->encode( $buffer, $self->_context->_encode_check )
108 if $self->_context->encoding && $self->content_type =~ /^text|xml$|javascript$/;
9c4288ea 109
110 my $len = length($buffer);
111 $self->_writer->write($buffer);
112
113 return $len;
114}
115
9c4288ea 116sub finalize_headers {
117 my ($self) = @_;
9c4288ea 118 return;
119}
120
e67f0874 121sub from_psgi_response {
122 my ($self, $psgi_res) = @_;
b194746d 123 if(blessed($psgi_res) && $psgi_res->can('as_psgi')) {
124 $psgi_res = $psgi_res->as_psgi;
125 }
e67f0874 126 if(ref $psgi_res eq 'ARRAY') {
127 my ($status, $headers, $body) = @$psgi_res;
128 $self->status($status);
4491e0cc 129 $self->headers(HTTP::Headers->new(@$headers));
8a3dcb98 130 $self->body($body);
e67f0874 131 } elsif(ref $psgi_res eq 'CODE') {
132 $psgi_res->(sub {
4491e0cc 133 my $response = shift;
134 my ($status, $headers, $maybe_body) = @$response;
e67f0874 135 $self->status($status);
4491e0cc 136 $self->headers(HTTP::Headers->new(@$headers));
8a3dcb98 137 if(defined $maybe_body) {
138 $self->body($maybe_body);
e67f0874 139 } else {
140 return $self->write_fh;
141 }
4491e0cc 142 });
143 } else {
e67f0874 144 die "You can't set a Catalyst response from that, expect a valid PSGI response";
145 }
146}
147
fc7ec1d9 148=head1 NAME
149
910410b8 150Catalyst::Response - stores output responding to the current client request
fc7ec1d9 151
152=head1 SYNOPSIS
153
fbcc39ad 154 $res = $c->response;
155 $res->body;
aa9e8261 156 $res->code;
fbcc39ad 157 $res->content_encoding;
158 $res->content_length;
159 $res->content_type;
160 $res->cookies;
fbcc39ad 161 $res->header;
162 $res->headers;
163 $res->output;
164 $res->redirect;
165 $res->status;
166 $res->write;
b22c6668 167
fc7ec1d9 168=head1 DESCRIPTION
169
910410b8 170This is the Catalyst Response class, which provides methods for responding to
46372e65 171the current client request. The appropriate L<Catalyst::Engine> for your environment
172will turn the Catalyst::Response into a HTTP Response and return it to the client.
b22c6668 173
174=head1 METHODS
fc7ec1d9 175
08a2c908 176=head2 $res->body( $text | $fh | $iohandle_object )
e060fe05 177
178 $c->response->body('Catalyst rocks!');
06e1b616 179
46372e65 180Sets or returns the output (text or binary data). If you are returning a large body,
2f381252 181you might want to use a L<IO::Handle> type of object (Something that implements the read method
46372e65 182in the same fashion), or a filehandle GLOB. Catalyst
183will write it piece by piece into the response.
06e1b616 184
490b7a80 185When using a L<IO::Handle> type of object and no content length has been
186already set in the response headers Catalyst will make a reasonable attempt
187to determine the size of the Handle. Depending on the implementation of your
188handle object, setting the content length may fail. If it is at all possible
189for you to determine the content length of your handle object,
4a178c0d 190it is recommended that you set the content length in the response headers
490b7a80 191yourself, which will be respected and sent by Catalyst in the response.
192
efeeb257 193Please note that the object needs to implement C<getline>, not just
194C<read>.
195
196Starting from version 5.90060, when using an L<IO::Handle> object, you
197may want to use L<Plack::Middleware::XSendfile>, to delegate the
198actual serving to the frontend server. To do so, you need to pass to
199C<body> an IO object with a C<path> method. This can be achieved in
200two ways.
201
202Either using L<Plack::Util>:
203
204 my $fh = IO::File->new($file, 'r');
205 Plack::Util::set_io_path($fh, $file);
206
207Or using L<IO::File::WithPath>
208
209 my $fh = IO::File::WithPath->new($file, 'r');
210
211And then passing the filehandle to body and setting headers, if needed.
212
213 $c->response->body($fh);
214 $c->response->headers->content_type('text/plain');
215 $c->response->headers->content_length(-s $file);
216 $c->response->headers->last_modified((stat($file))[9]);
217
218L<Plack::Middleware::XSendfile> can be loaded in the application so:
219
220 __PACKAGE__->config(
221 psgi_middleware => [
222 'XSendfile',
223 # other middlewares here...
224 ],
225 );
226
227B<Beware> that loading the middleware without configuring the
228webserver to set the request header C<X-Sendfile-Type> to a supported
229type (C<X-Accel-Redirect> for nginx, C<X-Sendfile> for Apache and
230Lighttpd), could lead to the disclosure of private paths to malicious
231clients setting that header.
232
233Nginx needs the additional X-Accel-Mapping header to be set in the
234webserver configuration, so the middleware will replace the absolute
235path of the IO object with the internal nginx path. This is also
236useful to prevent a buggy app to server random files from the
237filesystem, as it's an internal redirect.
238
239An nginx configuration for FastCGI could look so:
240
241 server {
242 server_name example.com;
243 root /my/app/root;
244 location /private/repo/ {
245 internal;
246 alias /my/app/repo/;
247 }
248 location /private/staging/ {
249 internal;
250 alias /my/app/staging/;
251 }
252 location @proxy {
253 include /etc/nginx/fastcgi_params;
254 fastcgi_param SCRIPT_NAME '';
255 fastcgi_param PATH_INFO $fastcgi_script_name;
256 fastcgi_param HTTP_X_SENDFILE_TYPE X-Accel-Redirect;
257 fastcgi_param HTTP_X_ACCEL_MAPPING /my/app=/private;
258 fastcgi_pass unix:/my/app/run/app.sock;
259 }
260 }
261
262In the example above, passing filehandles with a local path matching
263/my/app/staging or /my/app/repo will be served by nginx. Passing paths
264with other locations will lead to an internal server error.
265
266Setting the body to a filehandle without the C<path> method bypasses
267the middleware completely.
268
269For Apache and Lighttpd, the mapping doesn't apply and setting the
270X-Sendfile-Type is enough.
271
02570318 272=head2 $res->has_body
273
274Predicate which returns true when a body has been set.
275
aa9e8261 276=head2 $res->code
277
278Alias for $res->status.
279
b5ecfcf0 280=head2 $res->content_encoding
b5176d9e 281
910410b8 282Shortcut for $res->headers->content_encoding.
b5176d9e 283
b5ecfcf0 284=head2 $res->content_length
b5176d9e 285
910410b8 286Shortcut for $res->headers->content_length.
b5176d9e 287
b5ecfcf0 288=head2 $res->content_type
b5176d9e 289
910410b8 290Shortcut for $res->headers->content_type.
b5176d9e 291
87e9f9ab 292This value is typically set by your view or plugin. For example,
293L<Catalyst::Plugin::Static::Simple> will guess the mime type based on the file
294it found, while L<Catalyst::View::TT> defaults to C<text/html>.
295
b5ecfcf0 296=head2 $res->cookies
fc7ec1d9 297
910410b8 298Returns a reference to a hash containing cookies to be set. The keys of the
299hash are the cookies' names, and their corresponding values are hash
7e743798 300references used to construct a L<CGI::Simple::Cookie> object.
fc7ec1d9 301
302 $c->response->cookies->{foo} = { value => '123' };
303
7e743798 304The keys of the hash reference on the right correspond to the L<CGI::Simple::Cookie>
910410b8 305parameters of the same name, except they are used without a leading dash.
306Possible parameters are:
ac965e92 307
b0ad47c1 308=over
ac965e92 309
71453caf 310=item value
ac965e92 311
71453caf 312=item expires
ac965e92 313
71453caf 314=item domain
ac965e92 315
71453caf 316=item path
317
318=item secure
319
b21bc468 320=item httponly
321
71453caf 322=back
ac965e92 323
b5ecfcf0 324=head2 $res->header
fbcc39ad 325
910410b8 326Shortcut for $res->headers->header.
fbcc39ad 327
b5ecfcf0 328=head2 $res->headers
fc7ec1d9 329
910410b8 330Returns an L<HTTP::Headers> object, which can be used to set headers.
fc7ec1d9 331
332 $c->response->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
333
b5ecfcf0 334=head2 $res->output
fc7ec1d9 335
910410b8 336Alias for $res->body.
fc7ec1d9 337
b5ecfcf0 338=head2 $res->redirect( $url, $status )
fc7ec1d9 339
2f381252 340Causes the response to redirect to the specified URL. The default status is
341C<302>.
fc7ec1d9 342
73a52566 343 $c->response->redirect( 'http://slashdot.org' );
344 $c->response->redirect( 'http://slashdot.org', 307 );
345
2f381252 346This is a convenience method that sets the Location header to the
347redirect destination, and then sets the response status. You will
ee24f3a8 348want to C< return > or C<< $c->detach() >> to interrupt the normal
2f381252 349processing flow if you want the redirect to occur straight away.
350
824a5eb0 351B<Note:> do not give a relative URL as $url, i.e: one that is not fully
352qualified (= C<http://...>, etc.) or that starts with a slash
353(= C</path/here>). While it may work, it is not guaranteed to do the right
354thing and is not a standard behaviour. You may opt to use uri_for() or
355uri_for_action() instead.
356
00038a21 357B<Note:> If $url is an object that does ->as_string (such as L<URI>, which is
358what you get from ->uri_for) we automatically call that to stringify. This
359should ease the common case usage
360
361 return $c->res->redirect( $c->uri_for(...));
362
73a52566 363=cut
364
365sub redirect {
366 my $self = shift;
fbcc39ad 367
368 if (@_) {
73a52566 369 my $location = shift;
f1bbebac 370 my $status = shift || 302;
73a52566 371
00038a21 372 if(blessed($location) && $location->can('as_string')) {
373 $location = $location->as_string;
374 }
375
73a52566 376 $self->location($location);
377 $self->status($status);
378 }
379
380 return $self->location;
381}
fc7ec1d9 382
059c085b 383=head2 $res->location
384
385Sets or returns the HTTP 'Location'.
386
b5ecfcf0 387=head2 $res->status
fc7ec1d9 388
910410b8 389Sets or returns the HTTP status.
fc7ec1d9 390
391 $c->response->status(404);
aa9e8261 392
393$res->code is an alias for this, to match HTTP::Response->code.
b0ad47c1 394
b5ecfcf0 395=head2 $res->write( $data )
fbcc39ad 396
dd096a3a 397Writes $data to the output stream. Calling this method will finalize your
398headers and send the headers and status code response to the client (so changing
399them afterwards is a waste... be sure to set your headers correctly first).
400
401You may call this as often as you want throughout your response cycle. You may
402even set a 'body' afterward. So for example you might write your HTTP headers
403and the HEAD section of your document and then set the body from a template
404driven from a database. In some cases this can seem to the client as if you had
405a faster overall response (but note that unless your server support chunked
406body your content is likely to get queued anyway (L<Starman> and most other
407http 1.1 webservers support this).
408
409If there is an encoding set, we encode each line of the response (the default
410encoding is UTF-8).
fbcc39ad 411
e37f92f5 412=head2 $res->write_fh
413
414Returns a PSGI $writer object that has two methods, write and close. You can
415close over this object for asynchronous and nonblocking applications. For
416example (assuming you are using a supporting server, like L<Twiggy>
417
418 package AsyncExample::Controller::Root;
419
420 use Moose;
421
422 BEGIN { extends 'Catalyst::Controller' }
423
424 sub prepare_cb {
425 my $write_fh = pop;
426 return sub {
427 my $message = shift;
428 $write_fh->write("Finishing: $message\n");
429 $write_fh->close;
430 };
431 }
432
433 sub anyevent :Local :Args(0) {
434 my ($self, $c) = @_;
435 my $cb = $self->prepare_cb($c->res->write_fh);
436
437 my $watcher;
438 $watcher = AnyEvent->timer(
439 after => 5,
440 cb => sub {
441 $cb->(scalar localtime);
442 undef $watcher; # cancel circular-ref
443 });
444 }
445
dd096a3a 446Like the 'write' method, calling this will finalize headers. Unlike 'write' when you
447can this it is assumed you are taking control of the response so the body is never
448finalized (there isn't one anyway) and you need to call the close method.
449
e4cc83b2 450=head2 $res->print( @data )
451
452Prints @data to the output stream, separated by $,. This lets you pass
453the response object to functions that want to write to an L<IO::Handle>.
454
8738b8fe 455=head2 $self->finalize_headers($c)
456
457Writes headers to response if not already written
458
e67f0874 459=head2 from_psgi_response
460
461Given a PSGI response (either three element ARRAY reference OR coderef expecting
462a $responder) set the response from it.
463
464Properly supports streaming and delayed response and / or async IO if running
465under an expected event loop.
466
b194746d 467If passed an object, will expect that object to do a method C<as_psgi>.
468
e67f0874 469Example:
470
471 package MyApp::Web::Controller::Test;
472
473 use base 'Catalyst::Controller';
474 use Plack::App::Directory;
475
476
477 my $app = Plack::App::Directory->new({ root => "/path/to/htdocs" })
478 ->to_app;
479
480 sub myaction :Local Args {
481 my ($self, $c) = @_;
faa1bcff 482 $c->res->from_psgi_response($app->($c->req->env));
e67f0874 483 }
484
485Please note this does not attempt to map or nest your PSGI application under
486the Controller and Action namespace or path.
487
faa02805 488=head2 DEMOLISH
489
490Ensures that the response is flushed and closed at the end of the
491request.
492
493=head2 meta
494
495Provided by Moose
496
e4cc83b2 497=cut
498
499sub print {
500 my $self = shift;
501 my $data = shift;
502
503 defined $self->write($data) or return;
504
505 for (@_) {
506 defined $self->write($,) or return;
507 defined $self->write($_) or return;
508 }
fe3083a8 509 defined $self->write($\) or return;
b0ad47c1 510
e4cc83b2 511 return 1;
512}
513
910410b8 514=head1 AUTHORS
fc7ec1d9 515
2f381252 516Catalyst Contributors, see Catalyst.pm
fc7ec1d9 517
518=head1 COPYRIGHT
519
b0ad47c1 520This library is free software. You can redistribute it and/or modify
61b1e958 521it under the same terms as Perl itself.
fc7ec1d9 522
523=cut
524
e5ecd5bc 525__PACKAGE__->meta->make_immutable;
526
fc7ec1d9 5271;