MT#3925 Migrate more common methods into Role.

agranig/rest
Andreas Granig 12 years ago
parent 8683e52cdd
commit 9ef4961e97

@ -5,9 +5,6 @@ use boolean qw(true);
use Data::HAL qw();
use Data::HAL::Link qw();
use Data::Record qw();
use DateTime::Format::HTTP qw();
use DateTime::Format::RFC3339 qw();
use Digest::SHA3 qw(sha3_256_base64);
use HTTP::Headers qw();
use HTTP::Headers::Util qw(split_header_words);
use HTTP::Status qw(:constants);
@ -15,11 +12,8 @@ use HTTP::Status qw(:constants);
use MooseX::ClassAttribute qw(class_has);
use NGCP::Panel::Form::Contact::Admin qw();
use NGCP::Panel::Form::Contact::Reseller qw();
use NGCP::Panel::ValidateJSON qw();
use Path::Tiny qw(path);
use Regexp::Common qw(delimited); # $RE{delimited}
use Safe::Isa qw($_isa);
use Types::Standard qw(InstanceOf);
BEGIN { extends 'Catalyst::Controller::ActionRole'; }
require Catalyst::ActionRole::ACL;
require Catalyst::ActionRole::CheckTrailingSlash;
@ -32,7 +26,6 @@ with 'NGCP::Panel::Role::API';
class_has('dispatch_path', is => 'ro', default => '/api/contacts/');
class_has('relation', is => 'ro', default => 'http://purl.org/sipwise/ngcp-api/#rel-contacts');
has('last_modified', is => 'rw', isa => InstanceOf['DateTime']);
__PACKAGE__->config(
action => {
@ -170,42 +163,6 @@ sub allowed_methods : Private {
return [sort @allow];
}
sub cached : Private {
my ($self, $c) = @_;
my $response = $c->cache->get($c->request->uri->canonical->as_string);
unless ($response) {
$c->log->info('not cached');
return;
}
my $matched_tag = $c->request->header('If-None-Match') && ('*' eq $c->request->header('If-None-Match'))
|| (grep {$response->header('ETag') eq $_} Data::Record->new({
split => qr/\s*,\s*/, unless => $RE{delimited}{-delim => q(")},
})->records($c->request->header('If-None-Match')));
my $not_modified = $c->request->header('If-Modified-Since')
&& !($self->last_modified < DateTime::Format::HTTP->parse_datetime($c->request->header('If-Modified-Since')));
if (
$matched_tag && $not_modified
|| $matched_tag
|| $not_modified
) {
$c->response->status(HTTP_NOT_MODIFIED);
$c->response->headers($response->headers);
$c->log->info('cached');
return 1;
}
$c->log->info('stale');
return;
}
sub etag : Private {
my ($self, $octets) = @_;
return sprintf '"ni:/sha3-256;%s"', sha3_256_base64($octets);
}
sub expires : Private {
my ($self) = @_;
return DateTime->now->clone->add(years => 1); # XXX insert product end-of-life
}
sub hal_from_contact : Private {
my ($self, $contact) = @_;

@ -26,7 +26,7 @@ use JSON qw();
use JSON::Pointer qw();
use MooseX::ClassAttribute qw(class_has);
use NGCP::Panel::Form::Contact::Reseller qw();
use NGCP::Panel::ValidateJSON qw();
use NGCP::Panel::Utils::ValidateJSON qw();
use Path::Tiny qw(path);
use Regexp::Common qw(delimited); # $RE{delimited}
use Safe::Isa qw($_isa);
@ -128,7 +128,7 @@ sub PATCH : Allow {
};
last unless $self->valid_precondition($c, $cached->header('ETag'), 'contact');
try {
NGCP::Panel::ValidateJSON->new($cached->content);
NGCP::Panel::Utils::ValidateJSON->new($cached->content);
$entity = JSON::decode_json($cached->content);
} catch($e) {
die "cache poisoned: $e";
@ -256,7 +256,7 @@ sub PUT : Allow {
};
last unless $self->valid_precondition($c, $cached->header('ETag'), 'contact');
try {
NGCP::Panel::ValidateJSON->new($cached->content);
NGCP::Panel::Utils::ValidateJSON->new($cached->content);
$entity = JSON::decode_json($cached->content);
} catch($e) {
die "cache poisoned: $e";
@ -550,7 +550,7 @@ sub require_valid_patch : Private {
sub require_wellformed_json : Private {
my ($self, $c, $media_type, $patch) = @_;
try {
NGCP::Panel::ValidateJSON->new($patch);
NGCP::Panel::Utils::ValidateJSON->new($patch);
} catch($e) {
$c->response->status(HTTP_BAD_REQUEST);
$c->response->header('Content-Language' => 'en');

@ -22,7 +22,7 @@ use JE qw();
use JSON qw();
use MooseX::ClassAttribute qw(class_has);
use NGCP::Panel::Form::Contact::Reseller qw();
use NGCP::Panel::ValidateJSON qw();
use NGCP::Panel::Utils::ValidateJSON qw();
use Path::Tiny qw(path);
use Regexp::Common qw(delimited); # $RE{delimited}
use Safe::Isa qw($_isa);
@ -286,7 +286,7 @@ sub require_body : Private {
sub require_wellformed_json : Private {
my ($self, $c, $media_type, $patch) = @_;
try {
NGCP::Panel::ValidateJSON->new($patch);
NGCP::Panel::Utils::ValidateJSON->new($patch);
} catch($e) {
$c->response->status(HTTP_BAD_REQUEST);
$c->response->header('Content-Language' => 'en');

@ -25,7 +25,7 @@ use JE qw();
use JSON qw();
use JSON::Pointer qw();
use MooseX::ClassAttribute qw(class_has);
use NGCP::Panel::ValidateJSON qw();
use NGCP::Panel::Utils::ValidateJSON qw();
use Path::Tiny qw(path);
use Regexp::Common qw(delimited); # $RE{delimited}
use Safe::Isa qw($_isa);
@ -127,7 +127,7 @@ sub PATCH : Allow {
};
last unless $self->valid_precondition($c, $cached->header('ETag'), 'contract');
try {
NGCP::Panel::ValidateJSON->new($cached->content);
NGCP::Panel::Utils::ValidateJSON->new($cached->content);
$entity = JSON::decode_json($cached->content);
} catch($e) {
die "cache poisoned: $e";
@ -240,7 +240,7 @@ sub PUT : Allow {
};
last unless $self->valid_precondition($c, $cached->header('ETag'), 'contract');
try {
NGCP::Panel::ValidateJSON->new($cached->content);
NGCP::Panel::Utils::ValidateJSON->new($cached->content);
$entity = JSON::decode_json($cached->content);
} catch($e) {
die "cache poisoned: $e";
@ -518,7 +518,7 @@ sub require_valid_patch : Private {
sub require_wellformed_json : Private {
my ($self, $c, $media_type, $patch) = @_;
try {
NGCP::Panel::ValidateJSON->new($patch);
NGCP::Panel::Utils::ValidateJSON->new($patch);
} catch($e) {
$c->response->status(HTTP_BAD_REQUEST);
$c->response->header('Content-Language' => 'en');

@ -6,6 +6,14 @@ use JSON qw();
use HTTP::Status qw(:constants);
use Safe::Isa qw($_isa);
use Try::Tiny;
use Digest::SHA3 qw(sha3_256_base64);
use DateTime::Format::HTTP qw();
use DateTime::Format::RFC3339 qw();
use Types::Standard qw(InstanceOf);
use Regexp::Common qw(delimited); # $RE{delimited}
use NGCP::Panel::Utils::ValidateJSON qw();
has('last_modified', is => 'rw', isa => InstanceOf['DateTime']);
sub get_valid_post_data {
my ($self, %params) = @_;
@ -108,7 +116,7 @@ sub require_body {
sub require_wellformed_json {
my ($self, $c, $media_type, $patch) = @_;
try {
NGCP::Panel::ValidateJSON->new($patch);
NGCP::Panel::Utils::ValidateJSON->new($patch);
} catch {
$self->error($c, HTTP_BAD_REQUEST, "The entity is not a well-formed '$media_type' document. $_");
return;
@ -116,7 +124,42 @@ sub require_wellformed_json {
return 1;
}
sub cached {
my ($self, $c) = @_;
my $response = $c->cache->get($c->request->uri->canonical->as_string);
unless ($response) {
$c->log->info('not cached');
return;
}
my $matched_tag = $c->request->header('If-None-Match') && ('*' eq $c->request->header('If-None-Match'))
|| (grep {$response->header('ETag') eq $_} Data::Record->new({
split => qr/\s*,\s*/, unless => $RE{delimited}{-delim => q(")},
})->records($c->request->header('If-None-Match')));
my $not_modified = $c->request->header('If-Modified-Since')
&& !($self->last_modified < DateTime::Format::HTTP->parse_datetime($c->request->header('If-Modified-Since')));
if (
$matched_tag && $not_modified
|| $matched_tag
|| $not_modified
) {
$c->response->status(HTTP_NOT_MODIFIED);
$c->response->headers($response->headers);
$c->log->info('cached');
return 1;
}
$c->log->info('stale');
return;
}
sub etag {
my ($self, $octets) = @_;
return sprintf '"ni:/sha3-256;%s"', sha3_256_base64($octets);
}
sub expires {
my ($self) = @_;
return DateTime->now->clone->add(years => 1); # XXX insert product end-of-life
}
1;
# vim: set tabstop=4 expandtab:

@ -1,4 +1,4 @@
package NGCP::Panel::ValidateJSON;
package NGCP::Panel::Utils::ValidateJSON;
use Sipwise::Base;
extends 'JSON::Tiny::Subclassable';
Loading…
Cancel
Save