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