diff options
author | dakkar <dakkar@thenautilus.net> | 2014-12-27 14:28:17 +0000 |
---|---|---|
committer | dakkar <dakkar@thenautilus.net> | 2014-12-27 14:28:17 +0000 |
commit | ae91140cf2604bfc4f9330c876ba4a6a9a0b18e8 (patch) | |
tree | 59be50074693e49cb5d93e8177ebe415acbdde28 | |
parent | authenticate client tests (diff) | |
download | net-hawk-ae91140cf2604bfc4f9330c876ba4a6a9a0b18e8.tar.gz net-hawk-ae91140cf2604bfc4f9330c876ba4a6a9a0b18e8.tar.bz2 net-hawk-ae91140cf2604bfc4f9330c876ba4a6a9a0b18e8.zip |
porting to Perl 6!
-rw-r--r-- | lib/Net/Hawk/Errors.pm | 51 | ||||
-rw-r--r-- | lib/Net/Hawk/Utils.pm | 119 | ||||
-rw-r--r-- | t/tests/Net/Hawk/Utils.t | 30 |
3 files changed, 97 insertions, 103 deletions
diff --git a/lib/Net/Hawk/Errors.pm b/lib/Net/Hawk/Errors.pm index befd142..3172865 100644 --- a/lib/Net/Hawk/Errors.pm +++ b/lib/Net/Hawk/Errors.pm @@ -1,42 +1,17 @@ -package Net::Hawk::Errors; -use strict; -use warnings; -use 5.010; - -package Net::Hawk::Errors::base { - use Moo; - use Types::Standard qw(Str); - with 'Throwable'; - use overload - q{""} => 'as_string', - fallback => 1; - - has message => ( - is => 'ro', - isa => Str, - required => 1, - ); - - sub as_string { $_[0]->message } -}; - -package Net::Hawk::Errors::BadRequest { - use Moo; extends 'Net::Hawk::Errors::base'; +package Net::Hawk::Errors { + use v6; + class base is Exception { + has $.text; + sub message { return "{.text}" } + } - has value => (is => 'ro'); + class BadRequest is base { + has $.value; - sub as_string { - my ($self) = @_; - return sprintf( - '%s (%s)', - $self->message, - $self->value // '<undef>', - ); + sub message { + return "{ .text } ({ .value // '<undef>' })"; + } } -}; - -package Net::Hawk::Errors::UnAuthorized { - use Moo; extends 'Net::Hawk::Errors::base'; -}; -1; + class UnAuthorized is base {} +} diff --git a/lib/Net/Hawk/Utils.pm b/lib/Net/Hawk/Utils.pm index 0c5e2fd..2d7bc1b 100644 --- a/lib/Net/Hawk/Utils.pm +++ b/lib/Net/Hawk/Utils.pm @@ -1,81 +1,70 @@ -package Net::Hawk::Utils; -use strict; -use warnings; -use Time::HiRes qw(gettimeofday); -use 5.010; -use Moo; -use Types::Standard 1.000003 qw(Str Int Object ArrayRef Optional Undef); -use Types::URI qw(Uri); -use Type::Params qw(compile); -use Net::Hawk::Errors; - -sub parse_content_type { - state $argcheck = compile(Object,Str|Undef); - my ($self,$header) = $argcheck->(@_); - return '' unless defined $header; - - my ($ret) = $header =~ m{^\s*(\S+?)\s*(;|$)}; - return lc($ret); -} +package Net::Hawk::Utils { + use v6; + use URI; + use Net::Hawk::Errors; + + proto parse_content_type($) returns Str is export {*} + multi parse_content_type(Str:U) returns Str { return '' } + multi parse_content_type(Str:D $header) returns Str { + my $ret = $header ~~ m{^ \s* (\S+?) \s* (\;|$) }; + return $ret[0].lc; + } -sub now_msecs { - state $argcheck = compile(Object,Int); - my ($self,$offset_ms) = $argcheck->(@_); + sub now_msecs(Int $offset_ms=0) returns Int is export { + return floor(now*1000) + $offset_ms; + } - my ($sec,$usec) = gettimeofday; - return $sec + int($usec/1000) + $offset_ms//0; -} + sub now_secs(Int $offset_ms=0) returns Int is export { + return floor(now_msecs($offset_ms)/1000); + } -sub now_secs { - state $argcheck = compile(Object,Int); - my ($self,$offset_ms) = $argcheck->(@_); + proto parse_authorization_header($,*@) returns Hash is export {*} + multi parse_authorization_header(Str:U,*@) returns Hash { + Net::Hawk::Errors::UnAuthorized.new(text=>'no header').throw + } + multi parse_authorization_header(Str:D $header, @keys=qw<id ts nonce hash ext mac app dlg>) returns Hash { + my $valid_keys = Set(@keys); - return int(now_msecs($offset_ms)/1000); -} + $header ~~ m:i{^ hawk [\: \s+ (.+) ]? $} + or Net::Hawk::Errors::BadRequest.new( + text => 'invalid header syntax', + value => $header, + ).throw; + my $attr_string = $/[0]; -sub parse_authorization_header { - state $argcheck = compile(Object,Str|Undef,Optional[ArrayRef]); - my ($self,$header,$keys) = $argcheck->(@_); - $keys //= [qw(id ts nonce hash ext mac app dlg)]; - my %valid_keys; @valid_keys{@$keys}=(); + my %attributes; - Net::Hawk::Errors::UnAuthorized->throw(message=>'no header') - unless $header; - my ($attr_string) = $header =~ m{^hawk(?:\s+(.+))?$}i - or Net::Hawk::Errors::BadRequest->throw( - message => 'invalid header syntax', - value => $header, - ); + my @attr_strings = split /\s* ',' \s*/, $attr_string; - my %attributes; + for @attr_strings -> $attr { + unless $attr ~~ m{^ (\w+) '="' (<-["\\]>*) '"' } { + Net::Hawk::Errors::BadRequest.new( + text => 'Bad header format', + value => $header, + ).throw; + } + my ($key,$value) = @(); - my @attr_strings = split /\s*,\s*/, $attr_string; - for my $attr (@attr_strings) { - my ($key,$value) = $attr =~ m{^(\w+)="([^"\\]*)"} - or Net::Hawk::Errors::BadRequest->throw( - message => 'Bad header format', + Net::Hawk::Errors::BadRequest.new( + text => "Unknown attribute $key", value => $header, - ); - - Net::Hawk::Errors::BadRequest->throw( - message => "Unknown attribute $key", - value => $header, - ) unless exists $valid_keys{$key}; + ) unless $valid_keys{$key} :exists; - Net::Hawk::Errors::BadRequest->throw( - message => "Bad attribute value $value", - value => $header, - ) unless $value =~ m{^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$}; + Net::Hawk::Errors::BadRequest.new( + text => "Bad attribute value $value", + value => $header, + ) unless $value ~~ m{^<[ \w !#$%&'()*+,\-./:;\<=\>?@\[\]^`{|}~ ]>+$}; - Net::Hawk::Errors::BadRequest->throw( - message => "Duplicate attribute $key", - value => $header, - ) if exists $attributes{$key}; + Net::Hawk::Errors::BadRequest.new( + text => "Duplicate attribute $key", + value => $header, + ) if %attributes{$key} :exists; - $attributes{$key}=$value; - } + %attributes{$key} = ~$value; + } - return \%attributes; + return %attributes; + } } 1; diff --git a/t/tests/Net/Hawk/Utils.t b/t/tests/Net/Hawk/Utils.t new file mode 100644 index 0000000..126450e --- /dev/null +++ b/t/tests/Net/Hawk/Utils.t @@ -0,0 +1,30 @@ +#!perl6 +use v6; +use Test; +use Net::Hawk::Utils; + +subtest { + is(parse_content_type(Str),'','undef -> empty string'); + is(parse_content_type('text/plain'),'text/plain','simple'); + is(parse_content_type('text/plain; charset=utf-8'),'text/plain','ignore options'); +}; + +subtest { + throws_like { parse_authorization_header(Str) }, + Net::Hawk::Errors::UnAuthorized, + text => 'no header'; + + throws_like { parse_authorization_header('bad') }, + Net::Hawk::Errors::BadRequest, + text => 'invalid header syntax'; + + throws_like { parse_authorization_header('hawk: bad') }, + Net::Hawk::Errors::BadRequest, + text => 'Bad header format'; + + is_deeply( parse_authorization_header('hawk: id="1"'), + { id => '1' }, + 'ok parse'); +}; + +done; |