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 )