use URI::QueryParam;
use Moose::Util::TypeConstraints;
use Plack::Loader;
-use Plack::Middleware::Conditional;
-use Plack::Middleware::ReverseProxy;
+use Catalyst::EngineLoader;
+use Encode ();
+use utf8;
use namespace::clean -except => 'meta';
has env => (is => 'ro', writer => '_set_env', clearer => '_clear_env');
+my $WARN_ABOUT_ENV = 0;
+around env => sub {
+ my ($orig, $self, @args) = @_;
+ if(@args) {
+ warn "env as a writer is deprecated, you probably need to upgrade Catalyst::Engine::PSGI"
+ unless $WARN_ABOUT_ENV++;
+ return $self->_set_env(@args);
+ }
+ return $self->$orig;
+};
+
# input position and length
has read_length => (is => 'rw');
has read_position => (is => 'rw');
isa => 'CodeRef',
writer => '_set_response_cb',
clearer => '_clear_response_cb',
+ predicate => '_has_response_cb',
);
has _writer => (
$c->res->content_type('text/html; charset=utf-8');
my $name = ref($c)->config->{name} || join(' ', split('::', ref $c));
+
+ # Prevent Catalyst::Plugin::Unicode::Encoding from running.
+ # This is a little nasty, but it's the best way to be clean whether or
+ # not the user has an encoding plugin.
+
+ if ($c->can('encoding')) {
+ $c->{encoding} = '';
+ }
my ( $title, $error, $infos );
if ( $c->debug ) {
</body>
</html>
-
- # Trick IE
+ # Trick IE. Old versions of IE would display their own error page instead
+ # of ours if we'd give it less than 512 bytes.
$c->res->{body} .= ( ' ' x 512 );
+ $c->res->{body} = Encode::encode("UTF-8", $c->res->{body});
+
# Return 500
$c->res->status(500);
}
sub finalize_headers {
my ($self, $ctx) = @_;
+ # This is a less-than-pretty hack to avoid breaking the old
+ # Catalyst::Engine::PSGI. 5.9 Catalyst::Engine sets a response_cb and
+ # expects us to pass headers to it here, whereas Catalyst::Enngine::PSGI
+ # just pulls the headers out of $ctx->response in its run method and never
+ # 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;
+
my @headers;
$ctx->response->headers->scan(sub { push @headers, @_ });
sub finalize_uploads {
my ( $self, $c ) = @_;
+ # N.B. This code is theoretically entirely unneeded due to ->cleanup(1)
+ # on the HTTP::Body object.
my $request = $c->request;
foreach my $key (keys %{ $request->uploads }) {
my $upload = $request->uploads->{$key};
unless ( $request->_body ) {
my $type = $request->header('Content-Type');
$request->_body(HTTP::Body->new( $type, $length ));
+ $request->_body->cleanup(1); # Make extra sure!
$request->_body->tmpdir( $appclass->config->{uploadtmp} )
if exists $appclass->config->{uploadtmp};
}
my $base_path = $env->{SCRIPT_NAME} || "/";
# set the request URI
- my $req_uri = $env->{REQUEST_URI};
- $req_uri =~ s/\?.*$//;
- my $path = $req_uri;
- $path =~ s{^/+}{};
+ my $path;
+ if (!$ctx->config->{use_request_uri_for_path}) {
+ my $path_info = $env->{PATH_INFO};
+ if ( exists $env->{REDIRECT_URL} ) {
+ $base_path = $env->{REDIRECT_URL};
+ $base_path =~ s/\Q$path_info\E$//;
+ }
+ $path = $base_path . $path_info;
+ $path =~ s{^/+}{};
+ $path =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+ $path =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
+ }
+ else {
+ my $req_uri = $env->{REQUEST_URI};
+ $req_uri =~ s/\?.*$//;
+ $path = $req_uri;
+ $path =~ s{^/+}{};
+ }
# Using URI directly is way too slow, so we construct the URLs manually
my $uri_class = "URI::$scheme";
my $u = Catalyst::Request::Upload->new
(
size => $upload->{size},
- type => $headers->content_type,
+ type => scalar $headers->content_type,
headers => $headers,
tempname => $upload->{tempname},
filename => $upload->{filename},
The amount of input data that has already been read.
-=head2 $self->run($c)
+=head2 $self->run($app, $server)
-Start the engine. Implemented by the various engine classes.
+Start the engine. Builds a PSGI application and calls the
+run method on the server passed in, which then causes the
+engine to loop, handling requests..
=cut
sub run {
- my ($self, $app, $server, @args) = @_;
- # FIXME - Do something sensible with the options we're passed
- $server->run($self->build_psgi_app($app, @args));
+ my ($self, $app, $psgi, @args) = @_;
+ # @args left here rather than just a $options, $server for back compat with the
+ # old style scripts which send a few args, then a hashref
+
+ # They should never actually be used in the normal case as the Plack engine is
+ # passed in got all the 'standard' args via the loader in the script already.
+
+ # FIXME - we should stash the options in an attribute so that custom args
+ # like Gitalist's --git_dir are possible to get from the app without stupid tricks.
+ my $server = pop @args if (scalar @args && blessed $args[-1]);
+ my $options = pop @args if (scalar @args && ref($args[-1]) eq 'HASH');
+ # Back compat hack for applications with old (non Catalyst::Script) scripts to work in FCGI.
+ if (scalar @args && !ref($args[0])) {
+ if (my $listen = shift @args) {
+ $options->{listen} ||= [$listen];
+ }
+ }
+ if (! $server ) {
+ $server = Catalyst::EngineLoader->new(application_name => ref($self))->auto(%$options);
+ # We're not being called from a script, so auto detect what backend to
+ # run on. This should never happen, as mod_perl never calls ->run,
+ # instead the $app->handle method is called per request.
+ $app->log->warn("Not supplied a Plack engine, falling back to engine auto-loader (are your scripts ancient?)")
+ }
+ $server->run($psgi, $options);
}
+=head2 build_psgi_app ($app, @args)
+
+Builds and returns a PSGI application closure, wrapping it in the reverse proxy
+middleware if the using_frontend_proxy config setting is set.
+
+=cut
+
sub build_psgi_app {
my ($self, $app, @args) = @_;
- my $psgi_app = sub {
+ return sub {
my ($env) = @_;
return sub {
$app->handle_request(env => $env);
};
};
-
- $psgi_app = Plack::Middleware::Conditional->wrap(
- $psgi_app,
- condition => sub {
- my ($env) = @_;
- return if $app->config->{ignore_frontend_proxy};
- return $env->{REMOTE_ADDR} eq '127.0.0.1' || $app->config->{using_frontend_proxy};
- },
- builder => sub { Plack::Middleware::ReverseProxy->wrap($_[0]) },
- );
-
- return $psgi_app;
}
=head2 $self->write($c, $buffer)
$self->_prepared_write(1);
}
- return 0 if !defined $buffer;
+ $buffer = q[] unless defined $buffer;
my $len = length($buffer);
$self->_writer->write($buffer);
=head2 $self->env
-Hash containing enviroment variables including many special variables inserted
+Hash containing environment variables including many special variables inserted
by WWW server - like SERVER_*, REMOTE_*, HTTP_* ...
-Before accesing enviroment variables consider whether the same information is
+Before accessing environment variables consider whether the same information is
not directly available via Catalyst objects $c->request, $c->engine ...
-BEWARE: If you really need to access some enviroment variable from your Catalyst
+BEWARE: If you really need to access some environment variable from your Catalyst
application you should use $c->engine->env->{VARNAME} instead of $ENV{VARNAME},
-as in some enviroments the %ENV hash does not contain what you would expect.
+as in some environments the %ENV hash does not contain what you would expect.
=head1 AUTHORS