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