use HTTP::Body;
use HTTP::Headers;
use URI::QueryParam;
-use Moose::Util::TypeConstraints;
use Plack::Loader;
use Catalyst::EngineLoader;
use Encode ();
use namespace::clean -except => 'meta';
-has env => (is => 'ro', writer => '_set_env', clearer => '_clear_env');
+# Amount of data to read from input on each pass
+our $CHUNKSIZE = 64 * 1024;
+# XXX - this is only here for compat, do not use!
+has env => ( is => 'rw', writer => '_set_env' );
my $WARN_ABOUT_ENV = 0;
around env => sub {
my ($orig, $self, @args) = @_;
return $self->$orig;
};
-# input position and length
-has read_length => (is => 'rw');
-has read_position => (is => 'rw');
-
-has _prepared_write => (is => 'rw');
-
-has _response_cb => (
- is => 'ro',
- isa => 'CodeRef',
- writer => '_set_response_cb',
- clearer => '_clear_response_cb',
- predicate => '_has_response_cb',
-);
-
-subtype 'Catalyst::Engine::Types::Writer',
- as duck_type([qw(write close)]);
-
-has _writer => (
- is => 'ro',
- isa => 'Catalyst::Engine::Types::Writer',
- writer => '_set_writer',
- clearer => '_clear_writer',
-);
-
-# Amount of data to read from input on each pass
-our $CHUNKSIZE = 64 * 1024;
-
=head1 NAME
Catalyst::Engine - The Catalyst Engine
$self->write( $c, $body );
}
- $self->_writer->close;
- $self->_clear_writer;
- $self->_clear_env;
+ my $res = $c->response;
+ $res->_writer->close;
+ $res->_clear_writer;
return;
}
# sets response_cb. So take the lack of a response_cb as a sign that we
# don't need to set the headers.
- return unless $self->_has_response_cb;
+ return unless ($ctx->response->_has_response_cb);
my @headers;
$ctx->response->headers->scan(sub { push @headers, @_ });
- $self->_set_writer($self->_response_cb->([ $ctx->response->status, \@headers ]));
- $self->_clear_response_cb;
+ my $writer = $ctx->response->_response_cb->([ $ctx->response->status, \@headers ]);
+ $ctx->response->_set_writer($writer);
+ $ctx->response->_clear_response_cb;
return;
}
my ( $self, $c ) = @_;
my $appclass = ref($c) || $c;
- if ( my $length = $self->read_length ) {
- my $request = $c->request;
+ my $request = $c->request;
+ if ( my $length = $request->_read_length ) {
unless ( $request->_body ) {
my $type = $request->header('Content-Type');
$request->_body(HTTP::Body->new( $type, $length ));
}
# paranoia against wrong Content-Length header
- my $remaining = $length - $self->read_position;
+ my $remaining = $length - $c->request->_read_position;
if ( $remaining > 0 ) {
$self->finalize_read($c);
Catalyst::Exception->throw(
sub prepare_connection {
my ($self, $ctx) = @_;
- my $env = $self->env;
my $request = $ctx->request;
+ my $env = $ctx->request->env;
$request->address( $env->{REMOTE_ADDR} );
$request->hostname( $env->{REMOTE_HOST} )
sub prepare_headers {
my ($self, $ctx) = @_;
- my $env = $self->env;
+ my $env = $ctx->request->env;
my $headers = $ctx->request->headers;
for my $header (keys %{ $env }) {
sub prepare_path {
my ($self, $ctx) = @_;
- my $env = $self->env;
+ my $env = $ctx->request->env;
my $scheme = $ctx->request->secure ? 'https' : 'http';
my $host = $env->{HTTP_HOST} || $env->{SERVER_NAME};
sub prepare_query_parameters {
my ($self, $c) = @_;
- my $query_string = exists $self->env->{QUERY_STRING}
- ? $self->env->{QUERY_STRING}
+ my $env = $c->request->env;
+ my $query_string = exists $env->{QUERY_STRING}
+ ? $env->{QUERY_STRING}
: '';
# Check for keywords (no = signs)
sub prepare_read {
my ( $self, $c ) = @_;
- # Initialize the read position
- $self->read_position(0);
-
# Initialize the amount of data we think we need to read
- $self->read_length( $c->request->header('Content-Length') || 0 );
+ $c->request->_read_length;
}
=head2 $self->prepare_request(@arguments)
sub prepare_request {
my ($self, $ctx, %args) = @_;
- $self->_set_env($args{env});
+ $ctx->request->_set_env($args{env});
+ $self->_set_env($args{env}); # Nasty back compat!
+ $ctx->response->_set_response_cb($args{response_cb});
}
=head2 $self->prepare_uploads($c)
sub read {
my ( $self, $c, $maxlength ) = @_;
- my $remaining = $self->read_length - $self->read_position;
+ my $request = $c->request;
+ my $remaining = $request->_read_length - $request->_read_position;
$maxlength ||= $CHUNKSIZE;
# Are we done reading?
$self->finalize_read;
return;
}
- $self->read_position( $self->read_position + $rc );
+ my $request = $c->request;
+ $request->_read_position( $request->_read_position + $rc );
return $buffer;
}
else {
sub read_chunk {
my ($self, $ctx) = (shift, shift);
- return $self->env->{'psgi.input'}->read(@_);
+ return $ctx->request->env->{'psgi.input'}->read(@_);
}
=head2 $self->read_length
return sub {
my ($respond) = @_;
- $self->_set_response_cb($respond);
- $app->handle_request(env => $env);
+ $app->handle_request(env => $env, response_cb => $respond);
};
};
}
sub write {
my ( $self, $c, $buffer ) = @_;
- unless ( $self->_prepared_write ) {
+ my $response = $c->response;
+ unless ( $response->_prepared_write ) {
$self->prepare_write($c);
- $self->_prepared_write(1);
+ $response->_set_prepared_write(1);
}
$buffer = q[] unless defined $buffer;
my $len = length($buffer);
- $self->_writer->write($buffer);
+ $c->res->_writer->write($buffer);
return $len;
}
use Moose;
use HTTP::Headers;
+use Moose::Util::TypeConstraints;
+use namespace::autoclean;
with 'MooseX::Emulate::Class::Accessor::Fast';
+has _prepared_write => (is => 'ro', writer => '_set_prepared_write');
+
+has _response_cb => (
+ is => 'ro',
+ isa => 'CodeRef',
+ writer => '_set_response_cb',
+ clearer => '_clear_response_cb',
+ predicate => '_has_response_cb',
+);
+
+subtype 'Catalyst::Engine::Types::Writer',
+ as duck_type([qw(write close)]);
+
+has _writer => (
+ is => 'ro',
+ isa => 'Catalyst::Engine::Types::Writer',
+ writer => '_set_writer',
+ clearer => '_clear_writer',
+ predicate => '_has_writer',
+);
+
+sub DEMOLISH { $_[0]->_writer->close if $_[0]->_has_writer }
+
has cookies => (is => 'rw', default => sub { {} });
has body => (is => 'rw', default => undef);
sub has_body { defined($_[0]->body) }
sub code { shift->status(@_) }
-no Moose;
-
=head1 NAME
Catalyst::Response - stores output responding to the current client request
Writes $data to the output stream.
-=head2 meta
-
-Provided by Moose
-
=head2 $res->print( @data )
Prints @data to the output stream, separated by $,. This lets you pass
the response object to functions that want to write to an L<IO::Handle>.
+=head2 DEMOLISH
+
+Ensures that the response is flushed and closed at the end of the
+request.
+
+=head2 meta
+
+Provided by Moose
+
=cut
sub print {