1 package Catalyst::Response;
5 use Moose::Util::TypeConstraints;
6 use namespace::autoclean;
7 use Scalar::Util 'blessed';
8 use Catalyst::Response::Writer;
9 use Catalyst::Utils ();
11 with 'MooseX::Emulate::Class::Accessor::Fast';
13 our $DEFAULT_ENCODE_CONTENT_TYPE_MATCH = qr{text|xml$|javascript$};
15 has encodable_content_type => (
18 default => sub { $DEFAULT_ENCODE_CONTENT_TYPE_MATCH }
24 writer => '_set_response_cb',
25 clearer => '_clear_response_cb',
26 predicate => '_has_response_cb',
29 subtype 'Catalyst::Engine::Types::Writer',
30 as duck_type([qw(write close)]);
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
36 clearer => '_clear_writer',
37 predicate => '_has_writer',
39 builder => '_build_writer',
45 ## These two lines are probably crap now...
46 $self->_context->finalize_headers unless
47 $self->finalized_headers;
50 $self->headers->scan(sub { push @headers, @_ });
52 my $writer = $self->_response_cb->([ $self->status, \@headers ]);
53 $self->_clear_response_cb;
60 predicate=>'_has_write_fh',
62 builder=>'_build_write_fh',
66 my $writer = $_[0]->_writer; # We need to get the finalize headers side effect...
67 my $requires_encoding = $_[0]->encodable_response;
70 _context => $_[0]->_context,
71 _requires_encoding => $requires_encoding,
74 return bless \%fields, 'Catalyst::Response::Writer';
79 return if $self->_has_write_fh;
80 if($self->_has_writer) {
85 has cookies => (is => 'rw', default => sub { {} });
86 has body => (is => 'rw', default => undef);
87 sub has_body { defined($_[0]->body) }
89 has location => (is => 'rw');
90 has status => (is => 'rw', default => 200);
91 has finalized_headers => (is => 'rw', default => 0);
94 isa => 'HTTP::Headers',
95 handles => [qw(content_encoding content_length content_type content_type_charset header)],
96 default => sub { HTTP::Headers->new() },
103 clearer => '_clear_context',
106 before [qw(status headers content_encoding content_length content_type header)] => sub {
109 $self->_context->log->warn(
110 "Useless setting a header value after finalize_headers and the response callback has been called." .
111 " Not what you want." )
112 if ( $self->finalized_headers && !$self->_has_response_cb && @_ );
115 sub output { shift->body(@_) }
117 sub code { shift->status(@_) }
120 my ( $self, $buffer ) = @_;
122 # Finalize headers if someone manually writes output
123 $self->_context->finalize_headers unless $self->finalized_headers;
125 $buffer = q[] unless defined $buffer;
127 if($self->encodable_response) {
128 $buffer = $self->_context->encoding->encode( $buffer, $self->_context->_encode_check )
131 my $len = length($buffer);
132 $self->_writer->write($buffer);
137 sub finalize_headers {
142 sub from_psgi_response {
143 my ($self, $psgi_res) = @_;
144 if(blessed($psgi_res) && $psgi_res->can('as_psgi')) {
145 $psgi_res = $psgi_res->as_psgi;
147 if(ref $psgi_res eq 'ARRAY') {
148 my ($status, $headers, $body) = @$psgi_res;
149 $self->status($status);
150 $self->headers(HTTP::Headers->new(@$headers));
152 } elsif(ref $psgi_res eq 'CODE') {
154 my $response = shift;
155 my ($status, $headers, $maybe_body) = @$response;
156 $self->status($status);
157 $self->headers(HTTP::Headers->new(@$headers));
158 if(defined $maybe_body) {
159 $self->body($maybe_body);
161 return $self->write_fh;
165 die "You can't set a Catalyst response from that, expect a valid PSGI response";
171 Catalyst::Response - stores output responding to the current client request
178 $res->content_encoding;
179 $res->content_length;
191 This is the Catalyst Response class, which provides methods for responding to
192 the current client request. The appropriate L<Catalyst::Engine> for your environment
193 will turn the Catalyst::Response into a HTTP Response and return it to the client.
197 =head2 $res->body( $text | $fh | $iohandle_object )
199 $c->response->body('Catalyst rocks!');
201 Sets or returns the output (text or binary data). If you are returning a large body,
202 you might want to use a L<IO::Handle> type of object (Something that implements the getline method
203 in the same fashion), or a filehandle GLOB. These will be passed down to the PSGI
204 handler you are using and might be optimized using server specific abilities (for
205 example L<Twiggy> will attempt to server a real local file in a non blocking manner).
207 If you are using a filehandle as the body response you are responsible for
208 making sure it conforms to the L<PSGI> specification with regards to content
209 encoding. Unlike with scalar body values or when using the streaming interfaces
210 we currently do not attempt to normalize and encode your filehandle. In general
211 this means you should be sure to be sending bytes not UTF8 decoded multibyte
214 Most of the time when you do:
216 open(my $fh, '<:raw', $path);
218 You should be fine. If you open a filehandle with a L<PerlIO> layer you probably
219 are not fine. You can usually fix this by explicitly using binmode to set
220 the IOLayer to :raw. Its possible future versions of L<Catalyst> will try to
221 'do the right thing'.
223 When using a L<IO::Handle> type of object and no content length has been
224 already set in the response headers Catalyst will make a reasonable attempt
225 to determine the size of the Handle. Depending on the implementation of your
226 handle object, setting the content length may fail. If it is at all possible
227 for you to determine the content length of your handle object,
228 it is recommended that you set the content length in the response headers
229 yourself, which will be respected and sent by Catalyst in the response.
231 Please note that the object needs to implement C<getline>, not just
232 C<read>. Older versions of L<Catalyst> expected your filehandle like objects
233 to do read. If you have code written for this expectation and you cannot
234 change the code to meet the L<PSGI> specification, you can try the following
235 middleware L<Plack::Middleware::AdaptFilehandleRead> which will attempt to
236 wrap your object in an interface that so conforms.
238 Starting from version 5.90060, when using an L<IO::Handle> object, you
239 may want to use L<Plack::Middleware::XSendfile>, to delegate the
240 actual serving to the frontend server. To do so, you need to pass to
241 C<body> an IO object with a C<path> method. This can be achieved in
244 Either using L<Plack::Util>:
246 my $fh = IO::File->new($file, 'r');
247 Plack::Util::set_io_path($fh, $file);
249 Or using L<IO::File::WithPath>
251 my $fh = IO::File::WithPath->new($file, 'r');
253 And then passing the filehandle to body and setting headers, if needed.
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]);
260 L<Plack::Middleware::XSendfile> can be loaded in the application so:
265 # other middlewares here...
269 B<Beware> that loading the middleware without configuring the
270 webserver to set the request header C<X-Sendfile-Type> to a supported
271 type (C<X-Accel-Redirect> for nginx, C<X-Sendfile> for Apache and
272 Lighttpd), could lead to the disclosure of private paths to malicious
273 clients setting that header.
275 Nginx needs the additional X-Accel-Mapping header to be set in the
276 webserver configuration, so the middleware will replace the absolute
277 path of the IO object with the internal nginx path. This is also
278 useful to prevent a buggy app to server random files from the
279 filesystem, as it's an internal redirect.
281 An nginx configuration for FastCGI could look so:
284 server_name example.com;
286 location /private/repo/ {
290 location /private/staging/ {
292 alias /my/app/staging/;
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;
304 In 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
306 with other locations will lead to an internal server error.
308 Setting the body to a filehandle without the C<path> method bypasses
309 the middleware completely.
311 For Apache and Lighttpd, the mapping doesn't apply and setting the
312 X-Sendfile-Type is enough.
314 =head2 $res->has_body
316 Predicate which returns true when a body has been set.
320 Alias for $res->status.
322 =head2 $res->content_encoding
324 Shortcut for $res->headers->content_encoding.
326 =head2 $res->content_length
328 Shortcut for $res->headers->content_length.
330 =head2 $res->content_type
332 Shortcut for $res->headers->content_type.
334 This value is typically set by your view or plugin. For example,
335 L<Catalyst::Plugin::Static::Simple> will guess the mime type based on the file
336 it found, while L<Catalyst::View::TT> defaults to C<text/html>.
338 =head2 $res->content_type_charset
340 Shortcut for $res->headers->content_type_charset;
344 Returns a reference to a hash containing cookies to be set. The keys of the
345 hash are the cookies' names, and their corresponding values are hash
346 references used to construct a L<CGI::Simple::Cookie> object.
348 $c->response->cookies->{foo} = { value => '123' };
350 The keys of the hash reference on the right correspond to the L<CGI::Simple::Cookie>
351 parameters of the same name, except they are used without a leading dash.
352 Possible parameters are:
372 Shortcut for $res->headers->header.
376 Returns an L<HTTP::Headers> object, which can be used to set headers.
378 $c->response->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
382 Alias for $res->body.
384 =head2 $res->redirect( $url, $status )
386 Causes the response to redirect to the specified URL. The default status is
389 $c->response->redirect( 'http://slashdot.org' );
390 $c->response->redirect( 'http://slashdot.org', 307 );
392 This is a convenience method that sets the Location header to the
393 redirect destination, and then sets the response status. You will
394 want to C< return > or C<< $c->detach() >> to interrupt the normal
395 processing flow if you want the redirect to occur straight away.
397 B<Note:> do not give a relative URL as $url, i.e: one that is not fully
398 qualified (= 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
400 thing and is not a standard behaviour. You may opt to use uri_for() or
401 uri_for_action() instead.
403 B<Note:> If $url is an object that does ->as_string (such as L<URI>, which is
404 what you get from ->uri_for) we automatically call that to stringify. This
405 should ease the common case usage
407 return $c->res->redirect( $c->uri_for(...));
415 my $location = shift;
416 my $status = shift || 302;
418 if(blessed($location) && $location->can('as_string')) {
419 $location = $location->as_string;
422 $self->location($location);
423 $self->status($status);
426 return $self->location;
429 =head2 $res->location
431 Sets or returns the HTTP 'Location'.
435 Sets or returns the HTTP status.
437 $c->response->status(404);
439 $res->code is an alias for this, to match HTTP::Response->code.
441 =head2 $res->write( $data )
443 Writes $data to the output stream. Calling this method will finalize your
444 headers and send the headers and status code response to the client (so changing
445 them afterwards is a waste... be sure to set your headers correctly first).
447 You may call this as often as you want throughout your response cycle. You may
448 even set a 'body' afterward. So for example you might write your HTTP headers
449 and the HEAD section of your document and then set the body from a template
450 driven from a database. In some cases this can seem to the client as if you had
451 a faster overall response (but note that unless your server support chunked
452 body your content is likely to get queued anyway (L<Starman> and most other
453 http 1.1 webservers support this).
455 If there is an encoding set, we encode each line of the response (the default
458 =head2 $res->write_fh
460 Returns an instance of L<Catalyst::Response::Writer>, which is a lightweight
461 decorator over the PSGI C<$writer> object (see L<PSGI.pod\Delayed-Response-and-Streaming-Body>).
463 In addition to proxying the C<write> and C<close> method from the underlying PSGI
464 writer, this proxy object knows any application wide encoding, and provides a method
465 C<write_encoded> that will properly encode your written lines based upon your
466 encoding settings. By default in L<Catalyst> responses are UTF-8 encoded and this
467 is the encoding used if you respond via C<write_encoded>. If you want to handle
468 encoding yourself, you can use the C<write> method directly.
470 Encoding only applies to content types for which it matters. Currently the following
471 content types are assumed to need encoding: text (including HTML), xml and javascript.
473 We provide access to this object so that you can properly close over it for use in
474 asynchronous and nonblocking applications. For example (assuming you are using a supporting
475 server, like L<Twiggy>:
477 package AsyncExample::Controller::Root;
481 BEGIN { extends 'Catalyst::Controller' }
487 $write_fh->write("Finishing: $message\n");
492 sub anyevent :Local :Args(0) {
494 my $cb = $self->prepare_cb($c->res->write_fh);
497 $watcher = AnyEvent->timer(
500 $cb->(scalar localtime);
501 undef $watcher; # cancel circular-ref
505 Like the 'write' method, calling this will finalize headers. Unlike 'write' when you
506 can this it is assumed you are taking control of the response so the body is never
507 finalized (there isn't one anyway) and you need to call the close method.
509 =head2 $res->print( @data )
511 Prints @data to the output stream, separated by $,. This lets you pass
512 the response object to functions that want to write to an L<IO::Handle>.
514 =head2 $self->finalize_headers($c)
516 Writes headers to response if not already written
518 =head2 from_psgi_response
520 Given a PSGI response (either three element ARRAY reference OR coderef expecting
521 a $responder) set the response from it.
523 Properly supports streaming and delayed response and / or async IO if running
524 under an expected event loop.
526 If passed an object, will expect that object to do a method C<as_psgi>.
530 package MyApp::Web::Controller::Test;
532 use base 'Catalyst::Controller';
533 use Plack::App::Directory;
536 my $app = Plack::App::Directory->new({ root => "/path/to/htdocs" })
539 sub myaction :Local Args {
541 $c->res->from_psgi_response($app->($c->req->env));
544 Please note this does not attempt to map or nest your PSGI application under
545 the Controller and Action namespace or path.
547 =head2 encodable_content_type
549 This is a regular expression used to determine of the current content type
550 should be considered encodable. Currently we apply default encoding (usually
551 UTF8) to text type contents. Here's the default regular expression:
553 This would match content types like:
558 application/javascript
560 application/vnd.user+xml
562 B<NOTE>: We don't encode JSON content type responses by default since most
563 of the JSON serializers that are commonly used for this task will do so
564 automatically and we don't want to double encode. If you are not using a
565 tool like L<JSON> to produce JSON type content, (for example you are using
566 a template system, or creating the strings manually) you will need to either
567 encoding the body yourself:
569 $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) );
571 Or you can alter the regular expression using this attribute.
573 =head2 encodable_response
575 Given a L<Catalyst::Response> return true if its one that can be encoded.
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.
582 Note this does not inspect a body since we do allow automatic encoding on streaming
587 sub encodable_response {
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;
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;
598 ($self->content_type =~ m/${\$self->encodable_content_type}/) and
599 (!$has_manual_charset) and
600 (!$self->content_encoding || $self->content_encoding eq 'identity' )
610 Ensures that the response is flushed and closed at the end of the
623 defined $self->write($data) or return;
626 defined $self->write($,) or return;
627 defined $self->write($_) or return;
629 defined $self->write($\) or return;
636 Catalyst Contributors, see Catalyst.pm
640 This library is free software. You can redistribute it and/or modify
641 it under the same terms as Perl itself.
645 __PACKAGE__->meta->make_immutable;