package NGCP::Panel::Controller::API::Root; use Sipwise::Base; use namespace::sweep; use Encode qw(encode); use HTTP::Headers qw(); use HTTP::Response qw(); use HTTP::Status qw(:constants); use MooseX::ClassAttribute qw(class_has); use File::Find::Rule; BEGIN { extends 'Catalyst::Controller'; } require Catalyst::ActionRole::ACL; require Catalyst::ActionRole::CheckTrailingSlash; require Catalyst::ActionRole::HTTPMethods; require Catalyst::ActionRole::RequireSSL; with 'NGCP::Panel::Role::API'; class_has('dispatch_path', is => 'ro', default => '/api/'); __PACKAGE__->config( action => { map { $_ => { ACLDetachTo => [qw(API::Root invalid_user)], AllowedRole => 'api_admin', Args => 0, Does => [qw(ACL CheckTrailingSlash RequireSSL)], Method => $_, Path => __PACKAGE__->dispatch_path, } } @{ __PACKAGE__->allowed_methods } }, action_roles => [qw(HTTPMethods)], ); sub auto :Private { my ($self, $c) = @_; $self->set_body($c); $self->log_request($c); } sub GET : Allow { my ($self, $c) = @_; $c->stash(template => 'api/root.tt'); $c->forward($c->view); $c->response->headers(HTTP::Headers->new( Content_Language => 'en', Content_Type => 'application/xhtml+xml', $self->collections_link_headers, )); return; } sub HEAD : Allow { my ($self, $c) = @_; $c->forward(qw(GET)); $c->response->body(q()); return; } sub OPTIONS : Allow { my ($self, $c) = @_; my $allowed_methods = $self->allowed_methods; $c->response->headers(HTTP::Headers->new( Allow => $allowed_methods->join(', '), $self->collections_link_headers, )); $c->response->content_type('application/json'); $c->response->body(JSON::to_json({ methods => $allowed_methods })."\n"); return; } sub collections_link_headers : Private { my ($self) = @_; # figure out base path of our api modules my $libpath = $INC{"NGCP/Panel/Controller/API/Root.pm"}; $libpath =~ s/Root\.pm$//; # find all modules not called Root.pm and *Item.pm # (which should then be just collections) my $rootrule = File::Find::Rule->new->name('Root.pm'); my $itemrule = File::Find::Rule->new->name('*Item.pm'); my $rule = File::Find::Rule->new ->mindepth(1) ->maxdepth(1) ->name('*.pm') ->not($rootrule) ->not($itemrule); my @colls = $rule->in($libpath); # create Link header for each of the collections my @links = (); foreach my $mod(@colls) { # extract file base from path (e.g. Foo from lib/something/Foo.pm) $mod =~ s/^.+\/([a-zA-Z0-9_]+)\.pm$/$1/; my $rel = lc $mod; $mod = 'NGCP::Panel::Controller::API::'.$mod; my $dp = $mod->dispatch_path; push @links, Link => '<'.$dp.'>; rel="collection http://purl.org/sipwise/ngcp-api/#rel-'.$rel.'"'; } return @links; } sub invalid_user : Private { my ($self, $c, $ssl_client_m_serial) = @_; $self->error($c, HTTP_FORBIDDEN, "Invalid certificate serial number '$ssl_client_m_serial'."); return; } sub end : Private { my ($self, $c) = @_; $self->log_response($c); } # vim: set tabstop=4 expandtab: