package Tapir::Server;
=head1 NAME
Tapir::Server - An API server
=head1 DESCRIPTION
Mainly subclassed, this offers a base class for any implementation of the API.
=cut
use Moose;
use Params::Validate;
use Carp;
use Data::Dumper;
use Try::Tiny;
use Tapir::Logger;
sub is_valid_request {
my ($self, %opt) = @_;
return { };
}
# User specified arguments
has 'thrift_file' => (is => 'ro', required => 1);
has 'handlers' => (is => 'ro', default => sub { [] });
has 'transports' => (is => 'ro', default => sub { [] });
has 'logger' => (is => 'ro', lazy_build => 1);
sub add_handler {
my $self = shift;
my %opt = validate(@_, {
class => 1,
});
eval "require $opt{class}";
if ($@) {
croak "Failed to load class $opt{class}: $@";
}
my $service = $opt{class}->service;
if (! $service) {
croak "Class $opt{class} doesn't define a service";
}
my %methods = %{ $opt{class}->methods };
if (! %methods) {
croak "Class $opt{class} doesn't define any methods";
}
push @{ $self->handlers }, {
class => $opt{class},
service => $service,
methods => \%methods,
};
}
sub add_transport {
my $self = shift;
my %opt = validate(@_, {
class => 1,
options => { default => {} },
});
eval "require $opt{class}";
if ($@) {
croak "Failed to load class $opt{class}: $@";
}
my $transport;
try {
$transport = $opt{class}->new(
server => $self,
logger => $self->logger,
%{ $opt{options} }
);
$transport->setup();
} catch {
croak "Failed to load class $opt{class}: $_";
};
push @{ $self->transports }, $transport;
}
sub run {
my $self = shift;
if (! int @{ $self->transports }) {
croak "Can't run() without any transports defined";
}
$_->run() foreach @{ $self->transports };
}
sub _build_logger {
my $self = shift;
return Tapir::Logger->new(screen => 1);
}
1;