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