package Dancer::Handler;
use strict;
use warnings;
use Dancer::Logger;
use Dancer::GetOpt;
use Dancer::SharedData;
use Dancer::Renderer;
use Dancer::Config 'setting';
use Dancer::ModuleLoader;
use Encode;
# This is where we choose which application handler to return
sub get_handler {
my $handler;
if ($ENV{'PLACK_ENV'}) {
$handler = 'Dancer::Handler::PSGI';
setting('apphandler' => 'PSGI');
setting('environment' => $ENV{'PLACK_ENV'});
}
my $app_handler = setting('apphandler') || 'Standalone';
$handler = 'Dancer::Handler::' . $app_handler;
if (Dancer::ModuleLoader->load($handler)) {
Dancer::Logger::core('loading ' . $app_handler . ' handler');
return $handler->new;
}
else {
setting('apphandler', 'Standalone');
return get_handler();
}
}
# handle an incoming request, process it and return a response
sub handle_request {
my ($self, $request) = @_;
my $ip_addr = $request->remote_address || '-';
Dancer::SharedData->reset_timer;
Dancer::Logger::core("request: "
. $request->method . " "
. $request->path_info
. " from $ip_addr");
# save the request object
Dancer::SharedData->request($request);
# deserialize the request body if possible
$request = Dancer::Serializer->process_request($request)
if Dancer::App->current->setting('serializer');
# read cookies from client
Dancer::Cookies->init;
if (Dancer::Config::setting('auto_reload')) {
Dancer::App->reload_apps;
}
my $response;
eval {
$response = Dancer::Renderer->render_file
|| Dancer::Renderer->render_action
|| Dancer::Renderer->render_error(404);
};
if ($@) {
my $error = Dancer::Error->new(
code => 500,
title => "Runtime Error",
message => $@
);
$response = $error->render;
}
return $self->render_response($response);
}
# render a PSGI-formated response from a response built by
# handle_request()
sub render_response {
my ($self, $response) = @_;
my $content = $response->{content};
unless (ref($content) eq 'GLOB') {
my $charset = setting('charset');
my $ctype = $response->{content_type};
if ( $charset
&& $ctype =~ /^text\//
&& $ctype !~ /charset=/
&& utf8::is_utf8($content))
{
$content = Encode::encode($charset, $content);
$response->update_headers(
'Content-Type' => "$ctype; charset=$charset");
}
$content = [$content];
}
Dancer::Logger::core("response: " . $response->{status});
Dancer::SharedData->reset_all();
return [$response->{status}, $response->{headers}, $content];
}
# Fancy banner to print on startup
sub print_banner {
if (setting('access_log')) {
my $env = setting('environment');
print "== Entering the $env dance floor ...\n";
}
}
1;