even this change is appreciated.
[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;
b194746d 6use Scalar::Util 'blessed';
e8361cf8 7use Catalyst::Response::Writer;
6adc45cf 8use Catalyst::Utils ();
fc7ec1d9 9
eefc03e1 10use namespace::clean -except => ['meta'];
11
531f1ab6 12with 'MooseX::Emulate::Class::Accessor::Fast';
13
6adc45cf 14our $DEFAULT_ENCODE_CONTENT_TYPE_MATCH = qr{text|xml$|javascript$};
15
16has encodable_content_type => (
17 is => 'rw',
18 required => 1,
19 default => sub { $DEFAULT_ENCODE_CONTENT_TYPE_MATCH }
20);
21
faa02805 22has _response_cb => (
23 is => 'ro',
88e5a8b0 24 isa => 'CodeRef',
faa02805 25 writer => '_set_response_cb',
26 clearer => '_clear_response_cb',
27 predicate => '_has_response_cb',
28);
29
30subtype 'Catalyst::Engine::Types::Writer',
31 as duck_type([qw(write close)]);
32
33has _writer => (
34 is => 'ro',
46fff667 35 isa => 'Catalyst::Engine::Types::Writer', #Pointless since we control how this is built
36 #writer => '_set_writer', Now that its lazy I think this is safe to remove
faa02805 37 clearer => '_clear_writer',
38 predicate => '_has_writer',
46fff667 39 lazy => 1,
40 builder => '_build_writer',
faa02805 41);
42
46fff667 43sub _build_writer {
44 my $self = shift;
45
46 ## These two lines are probably crap now...
47 $self->_context->finalize_headers unless
48 $self->finalized_headers;
49
50 my @headers;
51 $self->headers->scan(sub { push @headers, @_ });
52
53 my $writer = $self->_response_cb->([ $self->status, \@headers ]);
54 $self->_clear_response_cb;
55
56 return $writer;
57}
58
e37f92f5 59has write_fh => (
60 is=>'ro',
a3c9ab76 61 predicate=>'_has_write_fh',
eb1f4b49 62 lazy=>1,
1f2a8069 63 builder=>'_build_write_fh',
64);
65
e8361cf8 66sub _build_write_fh {
67 my $writer = $_[0]->_writer; # We need to get the finalize headers side effect...
6adc45cf 68 my $requires_encoding = $_[0]->encodable_response;
e8361cf8 69 my %fields = (
70 _writer => $writer,
688e2420 71 _context => $_[0]->_context,
e8361cf8 72 _requires_encoding => $requires_encoding,
73 );
74
75 return bless \%fields, 'Catalyst::Response::Writer';
76}
e37f92f5 77
78sub DEMOLISH {
79 my $self = shift;
a3c9ab76 80 return if $self->_has_write_fh;
e37f92f5 81 if($self->_has_writer) {
82 $self->_writer->close
83 }
84}
faa02805 85
6680c772 86has cookies => (is => 'rw', default => sub { {} });
ffb43803 87has body => (is => 'rw', default => undef);
88sub has_body { defined($_[0]->body) }
99a543ee 89
059c085b 90has location => (is => 'rw');
6680c772 91has status => (is => 'rw', default => 200);
92has finalized_headers => (is => 'rw', default => 0);
059c085b 93has headers => (
94 is => 'rw',
9c331634 95 isa => 'HTTP::Headers',
6adc45cf 96 handles => [qw(content_encoding content_length content_type content_type_charset header)],
6680c772 97 default => sub { HTTP::Headers->new() },
98 required => 1,
99 lazy => 1,
059c085b 100);
258733f1 101has _context => (
102 is => 'rw',
103 weak_ref => 1,
104 clearer => '_clear_context',
105);
fc7ec1d9 106
18adb1ed 107before [qw(status headers content_encoding content_length content_type )] => sub {
9ae060f0 108 my $self = shift;
109
18adb1ed 110 $self->_context->log->warn(
6adc45cf 111 "Useless setting a header value after finalize_headers and the response callback has been called." .
18adb1ed 112 " Since we don't support tail headers this will not work as you might expect." )
113 if ( $self->_context && $self->finalized_headers && !$self->_has_response_cb && @_ );
114};
115
116# This has to be different since the first param to ->header is the header name and presumably
117# you should be able to request the header even after finalization, just not try to change it.
118before 'header' => sub {
119 my $self = shift;
120 my $header = shift;
121
122 $self->_context->log->warn(
123 "Useless setting a header value after finalize_headers and the response callback has been called." .
124 " Since we don't support tail headers this will not work as you might expect." )
ca6d4ff6 125 if ( $self->_context && $self->finalized_headers && !$self->_has_response_cb && @_ );
9ae060f0 126};
127
059c085b 128sub output { shift->body(@_) }
129
aa9e8261 130sub code { shift->status(@_) }
131
9c4288ea 132sub write {
133 my ( $self, $buffer ) = @_;
134
135 # Finalize headers if someone manually writes output
89ba65d5 136 $self->_context->finalize_headers unless $self->finalized_headers;
9c4288ea 137
138 $buffer = q[] unless defined $buffer;
5c397774 139
6adc45cf 140 if($self->encodable_response) {
141 $buffer = $self->_context->encoding->encode( $buffer, $self->_context->_encode_check )
142 }
9c4288ea 143
144 my $len = length($buffer);
145 $self->_writer->write($buffer);
146
147 return $len;
148}
149
9c056c82 150sub unencoded_write {
151 my ( $self, $buffer ) = @_;
152
153 # Finalize headers if someone manually writes output
154 $self->_context->finalize_headers unless $self->finalized_headers;
155
156 $buffer = q[] unless defined $buffer;
157
158 my $len = length($buffer);
159 $self->_writer->write($buffer);
160
161 return $len;
162}
163
9c4288ea 164sub finalize_headers {
165 my ($self) = @_;
9c4288ea 166 return;
167}
168
e67f0874 169sub from_psgi_response {
170 my ($self, $psgi_res) = @_;
b194746d 171 if(blessed($psgi_res) && $psgi_res->can('as_psgi')) {
172 $psgi_res = $psgi_res->as_psgi;
173 }
e67f0874 174 if(ref $psgi_res eq 'ARRAY') {
175 my ($status, $headers, $body) = @$psgi_res;
176 $self->status($status);
4491e0cc 177 $self->headers(HTTP::Headers->new(@$headers));
67fd25bc 178 # Can be arrayref or filehandle...
179 if(defined $body) { # probably paranoia
180 ref $body eq 'ARRAY' ? $self->body(join('', @$body)) : $self->body($body);
181 }
e67f0874 182 } elsif(ref $psgi_res eq 'CODE') {
183 $psgi_res->(sub {
4491e0cc 184 my $response = shift;
185 my ($status, $headers, $maybe_body) = @$response;
e67f0874 186 $self->status($status);
4491e0cc 187 $self->headers(HTTP::Headers->new(@$headers));
8a3dcb98 188 if(defined $maybe_body) {
67fd25bc 189 # Can be arrayref or filehandle...
190 ref $maybe_body eq 'ARRAY' ? $self->body(join('', @$maybe_body)) : $self->body($maybe_body);
e67f0874 191 } else {
192 return $self->write_fh;
193 }
88e5a8b0 194 });
4491e0cc 195 } else {
e67f0874 196 die "You can't set a Catalyst response from that, expect a valid PSGI response";
197 }
d2000928 198
75a7c429 199 return unless $self->_context->has_encoding;
cc7738c0 200
d2000928 201 # Encoding compatibilty. If the response set a charset, well... we need
202 # to assume its properly encoded and NOT encode for this response. Otherwise
203 # We risk double encoding.
204 if($self->content_type_charset) {
51b34249 205 # We have to do this since for backcompat reasons having a charset doesn't always
206 # mean that the body is already encoded :(
d2000928 207 $self->_context->clear_encoding;
208 }
e67f0874 209}
210
fc7ec1d9 211=head1 NAME
212
910410b8 213Catalyst::Response - stores output responding to the current client request
fc7ec1d9 214
215=head1 SYNOPSIS
216
fbcc39ad 217 $res = $c->response;
218 $res->body;
aa9e8261 219 $res->code;
fbcc39ad 220 $res->content_encoding;
221 $res->content_length;
222 $res->content_type;
223 $res->cookies;
fbcc39ad 224 $res->header;
225 $res->headers;
226 $res->output;
227 $res->redirect;
228 $res->status;
229 $res->write;
b22c6668 230
fc7ec1d9 231=head1 DESCRIPTION
232
910410b8 233This is the Catalyst Response class, which provides methods for responding to
46372e65 234the current client request. The appropriate L<Catalyst::Engine> for your environment
235will turn the Catalyst::Response into a HTTP Response and return it to the client.
b22c6668 236
237=head1 METHODS
fc7ec1d9 238
08a2c908 239=head2 $res->body( $text | $fh | $iohandle_object )
e060fe05 240
241 $c->response->body('Catalyst rocks!');
06e1b616 242
46372e65 243Sets or returns the output (text or binary data). If you are returning a large body,
88e5a8b0 244you might want to use a L<IO::Handle> type of object (Something that implements the getline method
77b5811a 245in the same fashion), or a filehandle GLOB. These will be passed down to the PSGI
246handler you are using and might be optimized using server specific abilities (for
247example L<Twiggy> will attempt to server a real local file in a non blocking manner).
06e1b616 248
6adc45cf 249If you are using a filehandle as the body response you are responsible for
566678d0 250making sure it conforms to the L<PSGI> specification with regards to content
6adc45cf 251encoding. Unlike with scalar body values or when using the streaming interfaces
252we currently do not attempt to normalize and encode your filehandle. In general
253this means you should be sure to be sending bytes not UTF8 decoded multibyte
254characters.
255
256Most of the time when you do:
257
258 open(my $fh, '<:raw', $path);
259
260You should be fine. If you open a filehandle with a L<PerlIO> layer you probably
261are not fine. You can usually fix this by explicitly using binmode to set
262the IOLayer to :raw. Its possible future versions of L<Catalyst> will try to
263'do the right thing'.
264
490b7a80 265When using a L<IO::Handle> type of object and no content length has been
266already set in the response headers Catalyst will make a reasonable attempt
267to determine the size of the Handle. Depending on the implementation of your
268handle object, setting the content length may fail. If it is at all possible
88e5a8b0 269for you to determine the content length of your handle object,
4a178c0d 270it is recommended that you set the content length in the response headers
490b7a80 271yourself, which will be respected and sent by Catalyst in the response.
272
efeeb257 273Please note that the object needs to implement C<getline>, not just
77b5811a 274C<read>. Older versions of L<Catalyst> expected your filehandle like objects
275to do read. If you have code written for this expectation and you cannot
276change the code to meet the L<PSGI> specification, you can try the following
277middleware L<Plack::Middleware::AdaptFilehandleRead> which will attempt to
278wrap your object in an interface that so conforms.
efeeb257 279
280Starting from version 5.90060, when using an L<IO::Handle> object, you
281may want to use L<Plack::Middleware::XSendfile>, to delegate the
282actual serving to the frontend server. To do so, you need to pass to
283C<body> an IO object with a C<path> method. This can be achieved in
284two ways.
285
286Either using L<Plack::Util>:
287
288 my $fh = IO::File->new($file, 'r');
289 Plack::Util::set_io_path($fh, $file);
290
291Or using L<IO::File::WithPath>
292
293 my $fh = IO::File::WithPath->new($file, 'r');
294
295And then passing the filehandle to body and setting headers, if needed.
296
297 $c->response->body($fh);
298 $c->response->headers->content_type('text/plain');
299 $c->response->headers->content_length(-s $file);
300 $c->response->headers->last_modified((stat($file))[9]);
301
302L<Plack::Middleware::XSendfile> can be loaded in the application so:
303
304 __PACKAGE__->config(
305 psgi_middleware => [
306 'XSendfile',
307 # other middlewares here...
308 ],
309 );
310
311B<Beware> that loading the middleware without configuring the
312webserver to set the request header C<X-Sendfile-Type> to a supported
313type (C<X-Accel-Redirect> for nginx, C<X-Sendfile> for Apache and
314Lighttpd), could lead to the disclosure of private paths to malicious
315clients setting that header.
316
317Nginx needs the additional X-Accel-Mapping header to be set in the
318webserver configuration, so the middleware will replace the absolute
319path of the IO object with the internal nginx path. This is also
320useful to prevent a buggy app to server random files from the
321filesystem, as it's an internal redirect.
322
323An nginx configuration for FastCGI could look so:
324
325 server {
326 server_name example.com;
327 root /my/app/root;
328 location /private/repo/ {
329 internal;
330 alias /my/app/repo/;
331 }
332 location /private/staging/ {
333 internal;
334 alias /my/app/staging/;
335 }
336 location @proxy {
337 include /etc/nginx/fastcgi_params;
338 fastcgi_param SCRIPT_NAME '';
339 fastcgi_param PATH_INFO $fastcgi_script_name;
340 fastcgi_param HTTP_X_SENDFILE_TYPE X-Accel-Redirect;
341 fastcgi_param HTTP_X_ACCEL_MAPPING /my/app=/private;
342 fastcgi_pass unix:/my/app/run/app.sock;
343 }
344 }
345
346In the example above, passing filehandles with a local path matching
347/my/app/staging or /my/app/repo will be served by nginx. Passing paths
348with other locations will lead to an internal server error.
349
350Setting the body to a filehandle without the C<path> method bypasses
351the middleware completely.
352
353For Apache and Lighttpd, the mapping doesn't apply and setting the
354X-Sendfile-Type is enough.
355
02570318 356=head2 $res->has_body
357
358Predicate which returns true when a body has been set.
359
aa9e8261 360=head2 $res->code
361
362Alias for $res->status.
363
b5ecfcf0 364=head2 $res->content_encoding
b5176d9e 365
910410b8 366Shortcut for $res->headers->content_encoding.
b5176d9e 367
b5ecfcf0 368=head2 $res->content_length
b5176d9e 369
910410b8 370Shortcut for $res->headers->content_length.
b5176d9e 371
b5ecfcf0 372=head2 $res->content_type
b5176d9e 373
910410b8 374Shortcut for $res->headers->content_type.
b5176d9e 375
87e9f9ab 376This value is typically set by your view or plugin. For example,
377L<Catalyst::Plugin::Static::Simple> will guess the mime type based on the file
378it found, while L<Catalyst::View::TT> defaults to C<text/html>.
379
6adc45cf 380=head2 $res->content_type_charset
381
382Shortcut for $res->headers->content_type_charset;
383
b5ecfcf0 384=head2 $res->cookies
fc7ec1d9 385
910410b8 386Returns a reference to a hash containing cookies to be set. The keys of the
387hash are the cookies' names, and their corresponding values are hash
7e743798 388references used to construct a L<CGI::Simple::Cookie> object.
fc7ec1d9 389
390 $c->response->cookies->{foo} = { value => '123' };
391
7e743798 392The keys of the hash reference on the right correspond to the L<CGI::Simple::Cookie>
910410b8 393parameters of the same name, except they are used without a leading dash.
394Possible parameters are:
ac965e92 395
b0ad47c1 396=over
ac965e92 397
71453caf 398=item value
ac965e92 399
71453caf 400=item expires
ac965e92 401
71453caf 402=item domain
ac965e92 403
71453caf 404=item path
405
406=item secure
407
b21bc468 408=item httponly
409
71453caf 410=back
ac965e92 411
b5ecfcf0 412=head2 $res->header
fbcc39ad 413
910410b8 414Shortcut for $res->headers->header.
fbcc39ad 415
b5ecfcf0 416=head2 $res->headers
fc7ec1d9 417
910410b8 418Returns an L<HTTP::Headers> object, which can be used to set headers.
fc7ec1d9 419
420 $c->response->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
421
b5ecfcf0 422=head2 $res->output
fc7ec1d9 423
910410b8 424Alias for $res->body.
fc7ec1d9 425
b5ecfcf0 426=head2 $res->redirect( $url, $status )
fc7ec1d9 427
2f381252 428Causes the response to redirect to the specified URL. The default status is
429C<302>.
fc7ec1d9 430
73a52566 431 $c->response->redirect( 'http://slashdot.org' );
432 $c->response->redirect( 'http://slashdot.org', 307 );
433
2f381252 434This is a convenience method that sets the Location header to the
435redirect destination, and then sets the response status. You will
ee24f3a8 436want to C< return > or C<< $c->detach() >> to interrupt the normal
2f381252 437processing flow if you want the redirect to occur straight away.
438
824a5eb0 439B<Note:> do not give a relative URL as $url, i.e: one that is not fully
440qualified (= C<http://...>, etc.) or that starts with a slash
441(= C</path/here>). While it may work, it is not guaranteed to do the right
442thing and is not a standard behaviour. You may opt to use uri_for() or
443uri_for_action() instead.
444
00038a21 445B<Note:> If $url is an object that does ->as_string (such as L<URI>, which is
446what you get from ->uri_for) we automatically call that to stringify. This
447should ease the common case usage
448
449 return $c->res->redirect( $c->uri_for(...));
450
73a52566 451=cut
452
453sub redirect {
454 my $self = shift;
fbcc39ad 455
456 if (@_) {
73a52566 457 my $location = shift;
f1bbebac 458 my $status = shift || 302;
73a52566 459
00038a21 460 if(blessed($location) && $location->can('as_string')) {
461 $location = $location->as_string;
462 }
463
73a52566 464 $self->location($location);
465 $self->status($status);
466 }
467
468 return $self->location;
469}
fc7ec1d9 470
059c085b 471=head2 $res->location
472
473Sets or returns the HTTP 'Location'.
474
b5ecfcf0 475=head2 $res->status
fc7ec1d9 476
910410b8 477Sets or returns the HTTP status.
fc7ec1d9 478
479 $c->response->status(404);
aa9e8261 480
481$res->code is an alias for this, to match HTTP::Response->code.
b0ad47c1 482
b5ecfcf0 483=head2 $res->write( $data )
fbcc39ad 484
dd096a3a 485Writes $data to the output stream. Calling this method will finalize your
486headers and send the headers and status code response to the client (so changing
487them afterwards is a waste... be sure to set your headers correctly first).
488
489You may call this as often as you want throughout your response cycle. You may
490even set a 'body' afterward. So for example you might write your HTTP headers
491and the HEAD section of your document and then set the body from a template
492driven from a database. In some cases this can seem to the client as if you had
493a faster overall response (but note that unless your server support chunked
88e5a8b0 494body your content is likely to get queued anyway (L<Starman> and most other
dd096a3a 495http 1.1 webservers support this).
496
497If there is an encoding set, we encode each line of the response (the default
498encoding is UTF-8).
fbcc39ad 499
e5ac67e5 500=head2 $res->unencoded_write( $data )
501
502Works just like ->write but we don't apply any content encoding to C<$data>. Use
503this if you are already encoding the $data or the data is arriving from an encoded
504storage.
505
e37f92f5 506=head2 $res->write_fh
507
e8361cf8 508Returns an instance of L<Catalyst::Response::Writer>, which is a lightweight
509decorator over the PSGI C<$writer> object (see L<PSGI.pod\Delayed-Response-and-Streaming-Body>).
510
511In addition to proxying the C<write> and C<close> method from the underlying PSGI
512writer, this proxy object knows any application wide encoding, and provides a method
513C<write_encoded> that will properly encode your written lines based upon your
514encoding settings. By default in L<Catalyst> responses are UTF-8 encoded and this
515is the encoding used if you respond via C<write_encoded>. If you want to handle
516encoding yourself, you can use the C<write> method directly.
517
518Encoding only applies to content types for which it matters. Currently the following
519content types are assumed to need encoding: text (including HTML), xml and javascript.
520
521We provide access to this object so that you can properly close over it for use in
522asynchronous and nonblocking applications. For example (assuming you are using a supporting
523server, like L<Twiggy>:
e37f92f5 524
525 package AsyncExample::Controller::Root;
526
527 use Moose;
528
529 BEGIN { extends 'Catalyst::Controller' }
530
531 sub prepare_cb {
532 my $write_fh = pop;
533 return sub {
534 my $message = shift;
535 $write_fh->write("Finishing: $message\n");
536 $write_fh->close;
537 };
538 }
539
540 sub anyevent :Local :Args(0) {
541 my ($self, $c) = @_;
542 my $cb = $self->prepare_cb($c->res->write_fh);
543
544 my $watcher;
545 $watcher = AnyEvent->timer(
546 after => 5,
547 cb => sub {
548 $cb->(scalar localtime);
549 undef $watcher; # cancel circular-ref
550 });
551 }
552
dd096a3a 553Like the 'write' method, calling this will finalize headers. Unlike 'write' when you
554can this it is assumed you are taking control of the response so the body is never
555finalized (there isn't one anyway) and you need to call the close method.
556
e4cc83b2 557=head2 $res->print( @data )
558
559Prints @data to the output stream, separated by $,. This lets you pass
560the response object to functions that want to write to an L<IO::Handle>.
561
e7ea7308 562=head2 $res->finalize_headers()
8738b8fe 563
564Writes headers to response if not already written
565
e67f0874 566=head2 from_psgi_response
567
568Given a PSGI response (either three element ARRAY reference OR coderef expecting
569a $responder) set the response from it.
570
571Properly supports streaming and delayed response and / or async IO if running
572under an expected event loop.
573
b194746d 574If passed an object, will expect that object to do a method C<as_psgi>.
575
e67f0874 576Example:
577
578 package MyApp::Web::Controller::Test;
579
580 use base 'Catalyst::Controller';
581 use Plack::App::Directory;
582
583
584 my $app = Plack::App::Directory->new({ root => "/path/to/htdocs" })
585 ->to_app;
586
587 sub myaction :Local Args {
588 my ($self, $c) = @_;
faa1bcff 589 $c->res->from_psgi_response($app->($c->req->env));
e67f0874 590 }
591
592Please note this does not attempt to map or nest your PSGI application under
aca337aa 593the Controller and Action namespace or path. You may wish to review 'PSGI Helpers'
594under L<Catalyst::Utils> for help in properly nesting applications.
595
596B<NOTE> If your external PSGI application returns a response that has a character
597set associated with the content type (such as "text/html; charset=UTF-8") we set
598$c->clear_encoding to remove any additional content type encoding processing later
599in the application (this is done to avoid double encoding issues).
e67f0874 600
6adc45cf 601=head2 encodable_content_type
602
603This is a regular expression used to determine of the current content type
604should be considered encodable. Currently we apply default encoding (usually
605UTF8) to text type contents. Here's the default regular expression:
606
607This would match content types like:
608
609 text/plain
610 text/html
611 text/xml
612 application/javascript
613 application/xml
614 application/vnd.user+xml
615
616B<NOTE>: We don't encode JSON content type responses by default since most
617of the JSON serializers that are commonly used for this task will do so
618automatically and we don't want to double encode. If you are not using a
619tool like L<JSON> to produce JSON type content, (for example you are using
620a template system, or creating the strings manually) you will need to either
621encoding the body yourself:
622
623 $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) );
624
625Or you can alter the regular expression using this attribute.
626
627=head2 encodable_response
628
88e5a8b0 629Given a L<Catalyst::Response> return true if its one that can be encoded.
6adc45cf 630
631 make sure there is an encoding set on the response
632 make sure the content type is encodable
633 make sure no content type charset has been already set to something different from the global encoding
634 make sure no content encoding is present.
635
636Note this does not inspect a body since we do allow automatic encoding on streaming
637type responses.
638
639=cut
640
641sub encodable_response {
642 my ($self) = @_;
643 return 0 unless $self->_context; # Cases like returning a HTTP Exception response you don't have a context here...
644 return 0 unless $self->_context->encoding;
645
d2000928 646 # The response is considered to have a 'manual charset' when a charset is already set on
647 # the content type of the response AND it is not the same as the one we set in encoding.
648 # If there is no charset OR we are asking for the one which is the same as the current
649 # required encoding, that is a flag that we want Catalyst to encode the response automatically.
6adc45cf 650 my $has_manual_charset = 0;
651 if(my $charset = $self->content_type_charset) {
652 $has_manual_charset = (uc($charset) ne uc($self->_context->encoding->mime_name)) ? 1:0;
653 }
654
d2000928 655 # Content type is encodable if it matches the regular expression stored in this attribute
656 my $encodable_content_type = $self->content_type =~ m/${\$self->encodable_content_type}/ ? 1:0;
657
658 # The content encoding is allowed (for charset encoding) only if its empty or is set to identity
659 my $allowed_content_encoding = (!$self->content_encoding || $self->content_encoding eq 'identity') ? 1:0;
660
661 # The content type must be an encodable type, and there must be NO manual charset and also
662 # the content encoding must be the allowed values;
6adc45cf 663 if(
d2000928 664 $encodable_content_type and
665 !$has_manual_charset and
666 $allowed_content_encoding
667 ) {
6adc45cf 668 return 1;
669 } else {
670 return 0;
671 }
672}
673
faa02805 674=head2 DEMOLISH
675
676Ensures that the response is flushed and closed at the end of the
677request.
678
679=head2 meta
680
681Provided by Moose
682
e4cc83b2 683=cut
684
685sub print {
686 my $self = shift;
687 my $data = shift;
688
689 defined $self->write($data) or return;
690
691 for (@_) {
692 defined $self->write($,) or return;
693 defined $self->write($_) or return;
694 }
fe3083a8 695 defined $self->write($\) or return;
b0ad47c1 696
e4cc83b2 697 return 1;
698}
699
910410b8 700=head1 AUTHORS
fc7ec1d9 701
2f381252 702Catalyst Contributors, see Catalyst.pm
fc7ec1d9 703
704=head1 COPYRIGHT
705
b0ad47c1 706This library is free software. You can redistribute it and/or modify
61b1e958 707it under the same terms as Perl itself.
fc7ec1d9 708
709=cut
710
e5ecd5bc 711__PACKAGE__->meta->make_immutable;
712
fc7ec1d9 7131;