Spike
view release on metacpan or search on metacpan
lib/Spike/Site/Router.pm view on Meta::CPAN
if (!$req_mtime || $req_mtime < $mtime) {
my $suffix = ($file =~ m!(\.[^/.]+)?$!)[0] || '.html';
$res->content_length($size);
$res->content_type(Plack::MIME->mime_type($suffix));
$res->body($fh);
}
else {
$res->status(HTTP_NOT_MODIFIED);
}
throw Spike::Error::HTTP_OK;
}
return;
}
sub _handle_error {
my ($self, $req, $res, $error, $errors) = @_;
$error = new Spike::Error::HTTP($error) if !ref $error;
my $class = ref $error;
my $is_http = $error->isa('Spike::Error::HTTP');
my $handlers = $errors->{$class} || ($is_http && $errors->{$error->value});
throw $error if !$handlers;
%$res = %{ $is_http ?
$req->new_response($error->value, $error->headers) :
$req->new_response(HTTP_INTERNAL_SERVER_ERROR)
};
my ($handler, $prepare, $finalize) = @$handlers;
$finalize->($req, $res,
$handler->($req, $res,
$prepare->($req, $res, $error)
)
);
}
sub handler {
my ($self, $req, $res) = @_;
my $path = $req->safe_path;
my @methods = $self->debug &&
$self->_try_static($req, $res, $path) ? qw(GET) : ();
my @handlers = $self->cache->get($path);
if (!@handlers) {
my ($found, $last_found) = $self->route->find($path);
@handlers = (
$found,
$self->_find_handlers($found || $last_found),
[ split m!/!, $path ],
);
$self->cache->store($path, @handlers);
}
my ($route, $prepare, $finalize, $errors, $names, $values) = @handlers;
$req->_bind_named_url_parameters(zip @$names, @$values);
my $handler;
if ($route) {
$handler = $route->method($req->method) || $route->method;
push @methods, $route->methods;
}
if (!$handler) {
if (@methods) {
$self->_handle_error($req, $res, new Spike::Error::HTTP(
HTTP_METHOD_NOT_ALLOWED, allow => join(', ', uniq @methods),
), $errors);
}
else {
$self->_handle_error($req, $res, HTTP_NOT_FOUND, $errors);
}
return;
}
eval {
$finalize->($req, $res,
$handler->($req, $res,
$prepare->($req, $res)
)
);
};
if (my $error = $@) {
if (blessed $error) {
if ($error->isa('Spike::Error::HTTP_OK')) {
throw $error;
}
elsif ($error->isa('Spike::Error::HTTP')) {
carp "HTTP error: status=".$error->value.", text=\"".$error->text."\"";
$self->_handle_error($req, $res, $error, $errors);
}
elsif ($error->isa('Spike::Error')) {
carp "Error: class=".ref($error).", text=\"".$error->text."\"";
$self->_handle_error($req, $res, $error, $errors);
}
else {
carp "Error: class=".ref($error).", text=\"".($error->can('text') ? $error->text : "$error")."\"";
$self->_handle_error($req, $res, HTTP_INTERNAL_SERVER_ERROR, $errors);
}
}
else {
carp $error;
$self->_handle_error($req, $res, HTTP_INTERNAL_SERVER_ERROR, $errors);
}
}
}
( run in 1.121 second using v1.01-cache-2.11-cpan-71847e10f99 )