up version in prep for release
[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;
fc7ec1d9 7
531f1ab6 8with 'MooseX::Emulate::Class::Accessor::Fast';
9
faa02805 10has _response_cb => (
11 is => 'ro',
12 isa => 'CodeRef',
13 writer => '_set_response_cb',
14 clearer => '_clear_response_cb',
15 predicate => '_has_response_cb',
16);
17
18subtype 'Catalyst::Engine::Types::Writer',
19 as duck_type([qw(write close)]);
20
21has _writer => (
22 is => 'ro',
23 isa => 'Catalyst::Engine::Types::Writer',
24 writer => '_set_writer',
25 clearer => '_clear_writer',
26 predicate => '_has_writer',
27);
28
e37f92f5 29has write_fh => (
30 is=>'ro',
a3c9ab76 31 predicate=>'_has_write_fh',
eb1f4b49 32 lazy=>1,
1f2a8069 33 builder=>'_build_write_fh',
34);
35
36sub _build_write_fh {
37 my $self = shift;
38 $self->_context->finalize_headers unless
39 $self->finalized_headers;
40 $self->_writer;
41};
e37f92f5 42
43sub DEMOLISH {
44 my $self = shift;
a3c9ab76 45 return if $self->_has_write_fh;
e37f92f5 46 if($self->_has_writer) {
47 $self->_writer->close
48 }
49}
faa02805 50
6680c772 51has cookies => (is => 'rw', default => sub { {} });
ffb43803 52has body => (is => 'rw', default => undef);
53sub has_body { defined($_[0]->body) }
99a543ee 54
059c085b 55has location => (is => 'rw');
6680c772 56has status => (is => 'rw', default => 200);
57has finalized_headers => (is => 'rw', default => 0);
059c085b 58has headers => (
59 is => 'rw',
9c331634 60 isa => 'HTTP::Headers',
059c085b 61 handles => [qw(content_encoding content_length content_type header)],
6680c772 62 default => sub { HTTP::Headers->new() },
63 required => 1,
64 lazy => 1,
059c085b 65);
258733f1 66has _context => (
67 is => 'rw',
68 weak_ref => 1,
69 clearer => '_clear_context',
70);
fc7ec1d9 71
059c085b 72sub output { shift->body(@_) }
73
aa9e8261 74sub code { shift->status(@_) }
75
9c4288ea 76sub write {
77 my ( $self, $buffer ) = @_;
78
79 # Finalize headers if someone manually writes output
89ba65d5 80 $self->_context->finalize_headers unless $self->finalized_headers;
9c4288ea 81
82 $buffer = q[] unless defined $buffer;
83
84 my $len = length($buffer);
85 $self->_writer->write($buffer);
86
87 return $len;
88}
89
9c4288ea 90sub finalize_headers {
91 my ($self) = @_;
92
93 # This is a less-than-pretty hack to avoid breaking the old
94 # Catalyst::Engine::PSGI. 5.9 Catalyst::Engine sets a response_cb and
95 # expects us to pass headers to it here, whereas Catalyst::Enngine::PSGI
96 # just pulls the headers out of $ctx->response in its run method and never
97 # sets response_cb. So take the lack of a response_cb as a sign that we
98 # don't need to set the headers.
99
100 return unless $self->_has_response_cb;
101
102 # If we already have a writer, we already did this, so don't do it again
103 return if $self->_has_writer;
104
105 my @headers;
106 $self->headers->scan(sub { push @headers, @_ });
107
108 my $writer = $self->_response_cb->([ $self->status, \@headers ]);
109 $self->_set_writer($writer);
110 $self->_clear_response_cb;
111
112 return;
113}
114
e67f0874 115sub from_psgi_response {
116 my ($self, $psgi_res) = @_;
117 if(ref $psgi_res eq 'ARRAY') {
118 my ($status, $headers, $body) = @$psgi_res;
119 $self->status($status);
4491e0cc 120 $self->headers(HTTP::Headers->new(@$headers));
e67f0874 121 if(ref $body eq 'ARRAY') {
122 $self->body(join '', grep defined, @$body);
123 } else {
124 $self->body($body);
125 }
126 } elsif(ref $psgi_res eq 'CODE') {
127 $psgi_res->(sub {
4491e0cc 128 my $response = shift;
129 my ($status, $headers, $maybe_body) = @$response;
e67f0874 130 $self->status($status);
4491e0cc 131 $self->headers(HTTP::Headers->new(@$headers));
e67f0874 132 if($maybe_body) {
133 if(ref $maybe_body eq 'ARRAY') {
134 $self->body(join '', grep defined, @$maybe_body);
135 } else {
136 $self->body($maybe_body);
137 }
138 } else {
139 return $self->write_fh;
140 }
4491e0cc 141 });
142 } else {
e67f0874 143 die "You can't set a Catalyst response from that, expect a valid PSGI response";
144 }
145}
146
fc7ec1d9 147=head1 NAME
148
910410b8 149Catalyst::Response - stores output responding to the current client request
fc7ec1d9 150
151=head1 SYNOPSIS
152
fbcc39ad 153 $res = $c->response;
154 $res->body;
aa9e8261 155 $res->code;
fbcc39ad 156 $res->content_encoding;
157 $res->content_length;
158 $res->content_type;
159 $res->cookies;
fbcc39ad 160 $res->header;
161 $res->headers;
162 $res->output;
163 $res->redirect;
164 $res->status;
165 $res->write;
b22c6668 166
fc7ec1d9 167=head1 DESCRIPTION
168
910410b8 169This is the Catalyst Response class, which provides methods for responding to
46372e65 170the current client request. The appropriate L<Catalyst::Engine> for your environment
171will turn the Catalyst::Response into a HTTP Response and return it to the client.
b22c6668 172
173=head1 METHODS
fc7ec1d9 174
08a2c908 175=head2 $res->body( $text | $fh | $iohandle_object )
e060fe05 176
177 $c->response->body('Catalyst rocks!');
06e1b616 178
46372e65 179Sets or returns the output (text or binary data). If you are returning a large body,
2f381252 180you might want to use a L<IO::Handle> type of object (Something that implements the read method
46372e65 181in the same fashion), or a filehandle GLOB. Catalyst
182will write it piece by piece into the response.
06e1b616 183
490b7a80 184When using a L<IO::Handle> type of object and no content length has been
185already set in the response headers Catalyst will make a reasonable attempt
186to determine the size of the Handle. Depending on the implementation of your
187handle object, setting the content length may fail. If it is at all possible
188for you to determine the content length of your handle object,
189it is recomended that you set the content length in the response headers
190yourself, which will be respected and sent by Catalyst in the response.
191
02570318 192=head2 $res->has_body
193
194Predicate which returns true when a body has been set.
195
aa9e8261 196=head2 $res->code
197
198Alias for $res->status.
199
b5ecfcf0 200=head2 $res->content_encoding
b5176d9e 201
910410b8 202Shortcut for $res->headers->content_encoding.
b5176d9e 203
b5ecfcf0 204=head2 $res->content_length
b5176d9e 205
910410b8 206Shortcut for $res->headers->content_length.
b5176d9e 207
b5ecfcf0 208=head2 $res->content_type
b5176d9e 209
910410b8 210Shortcut for $res->headers->content_type.
b5176d9e 211
87e9f9ab 212This value is typically set by your view or plugin. For example,
213L<Catalyst::Plugin::Static::Simple> will guess the mime type based on the file
214it found, while L<Catalyst::View::TT> defaults to C<text/html>.
215
b5ecfcf0 216=head2 $res->cookies
fc7ec1d9 217
910410b8 218Returns a reference to a hash containing cookies to be set. The keys of the
219hash are the cookies' names, and their corresponding values are hash
7e743798 220references used to construct a L<CGI::Simple::Cookie> object.
fc7ec1d9 221
222 $c->response->cookies->{foo} = { value => '123' };
223
7e743798 224The keys of the hash reference on the right correspond to the L<CGI::Simple::Cookie>
910410b8 225parameters of the same name, except they are used without a leading dash.
226Possible parameters are:
ac965e92 227
b0ad47c1 228=over
ac965e92 229
71453caf 230=item value
ac965e92 231
71453caf 232=item expires
ac965e92 233
71453caf 234=item domain
ac965e92 235
71453caf 236=item path
237
238=item secure
239
b21bc468 240=item httponly
241
71453caf 242=back
ac965e92 243
b5ecfcf0 244=head2 $res->header
fbcc39ad 245
910410b8 246Shortcut for $res->headers->header.
fbcc39ad 247
b5ecfcf0 248=head2 $res->headers
fc7ec1d9 249
910410b8 250Returns an L<HTTP::Headers> object, which can be used to set headers.
fc7ec1d9 251
252 $c->response->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
253
b5ecfcf0 254=head2 $res->output
fc7ec1d9 255
910410b8 256Alias for $res->body.
fc7ec1d9 257
b5ecfcf0 258=head2 $res->redirect( $url, $status )
fc7ec1d9 259
2f381252 260Causes the response to redirect to the specified URL. The default status is
261C<302>.
fc7ec1d9 262
73a52566 263 $c->response->redirect( 'http://slashdot.org' );
264 $c->response->redirect( 'http://slashdot.org', 307 );
265
2f381252 266This is a convenience method that sets the Location header to the
267redirect destination, and then sets the response status. You will
ee24f3a8 268want to C< return > or C<< $c->detach() >> to interrupt the normal
2f381252 269processing flow if you want the redirect to occur straight away.
270
824a5eb0 271B<Note:> do not give a relative URL as $url, i.e: one that is not fully
272qualified (= C<http://...>, etc.) or that starts with a slash
273(= C</path/here>). While it may work, it is not guaranteed to do the right
274thing and is not a standard behaviour. You may opt to use uri_for() or
275uri_for_action() instead.
276
73a52566 277=cut
278
279sub redirect {
280 my $self = shift;
fbcc39ad 281
282 if (@_) {
73a52566 283 my $location = shift;
f1bbebac 284 my $status = shift || 302;
73a52566 285
286 $self->location($location);
287 $self->status($status);
288 }
289
290 return $self->location;
291}
fc7ec1d9 292
059c085b 293=head2 $res->location
294
295Sets or returns the HTTP 'Location'.
296
b5ecfcf0 297=head2 $res->status
fc7ec1d9 298
910410b8 299Sets or returns the HTTP status.
fc7ec1d9 300
301 $c->response->status(404);
aa9e8261 302
303$res->code is an alias for this, to match HTTP::Response->code.
b0ad47c1 304
b5ecfcf0 305=head2 $res->write( $data )
fbcc39ad 306
307Writes $data to the output stream.
308
e37f92f5 309=head2 $res->write_fh
310
311Returns a PSGI $writer object that has two methods, write and close. You can
312close over this object for asynchronous and nonblocking applications. For
313example (assuming you are using a supporting server, like L<Twiggy>
314
315 package AsyncExample::Controller::Root;
316
317 use Moose;
318
319 BEGIN { extends 'Catalyst::Controller' }
320
321 sub prepare_cb {
322 my $write_fh = pop;
323 return sub {
324 my $message = shift;
325 $write_fh->write("Finishing: $message\n");
326 $write_fh->close;
327 };
328 }
329
330 sub anyevent :Local :Args(0) {
331 my ($self, $c) = @_;
332 my $cb = $self->prepare_cb($c->res->write_fh);
333
334 my $watcher;
335 $watcher = AnyEvent->timer(
336 after => 5,
337 cb => sub {
338 $cb->(scalar localtime);
339 undef $watcher; # cancel circular-ref
340 });
341 }
342
e4cc83b2 343=head2 $res->print( @data )
344
345Prints @data to the output stream, separated by $,. This lets you pass
346the response object to functions that want to write to an L<IO::Handle>.
347
8738b8fe 348=head2 $self->finalize_headers($c)
349
350Writes headers to response if not already written
351
e67f0874 352=head2 from_psgi_response
353
354Given a PSGI response (either three element ARRAY reference OR coderef expecting
355a $responder) set the response from it.
356
357Properly supports streaming and delayed response and / or async IO if running
358under an expected event loop.
359
360Example:
361
362 package MyApp::Web::Controller::Test;
363
364 use base 'Catalyst::Controller';
365 use Plack::App::Directory;
366
367
368 my $app = Plack::App::Directory->new({ root => "/path/to/htdocs" })
369 ->to_app;
370
371 sub myaction :Local Args {
372 my ($self, $c) = @_;
faa1bcff 373 $c->res->from_psgi_response($app->($c->req->env));
e67f0874 374 }
375
376Please note this does not attempt to map or nest your PSGI application under
377the Controller and Action namespace or path.
378
faa02805 379=head2 DEMOLISH
380
381Ensures that the response is flushed and closed at the end of the
382request.
383
384=head2 meta
385
386Provided by Moose
387
e4cc83b2 388=cut
389
390sub print {
391 my $self = shift;
392 my $data = shift;
393
394 defined $self->write($data) or return;
395
396 for (@_) {
397 defined $self->write($,) or return;
398 defined $self->write($_) or return;
399 }
fe3083a8 400 defined $self->write($\) or return;
b0ad47c1 401
e4cc83b2 402 return 1;
403}
404
910410b8 405=head1 AUTHORS
fc7ec1d9 406
2f381252 407Catalyst Contributors, see Catalyst.pm
fc7ec1d9 408
409=head1 COPYRIGHT
410
b0ad47c1 411This library is free software. You can redistribute it and/or modify
61b1e958 412it under the same terms as Perl itself.
fc7ec1d9 413
414=cut
415
e5ecd5bc 416__PACKAGE__->meta->make_immutable;
417
fc7ec1d9 4181;