File Coverage

blib/lib/Mojo/UserAgent/Role/Signature.pm
Criterion Covered Total %
statement 25 25 100.0
branch 8 10 80.0
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 42 44 95.4


line stmt bran cond sub pod time code
1             package Mojo::UserAgent::Role::Signature;
2 2     2   3618 use Mojo::Base -role;
  2         6  
  2         14  
3              
4 2     2   993 use Mojo::Loader qw(load_class);
  2         15  
  2         99  
5 2     2   12 use Mojo::Util qw(camelize);
  2         4  
  2         86  
6 2     2   510 use Mojo::UserAgent::Signature::Base;
  2         5  
  2         17  
7              
8             our $VERSION = '0.01';
9              
10             has signature_namespaces => sub { ['Mojo::UserAgent::Signature'] };
11             has 'signature';
12              
13             around build_tx => sub {
14             my ($orig, $self) = (shift, shift);
15             return $orig->($self, @_) unless $self->signature;
16             $self->signature->apply_signature($orig->($self, @_));
17             };
18              
19             sub initialize_signature {
20 2     2 1 6539 my $self = shift;
21 2 100       11 $self->load_signature(shift)->init($self, ref $_[0] ? $_[0] : {@_});
22             }
23              
24             sub load_signature {
25 2     2 1 7 my ($self, $name) = @_;
26              
27             # Try all namespaces and full module name
28 2 50       11 my $suffix = $name =~ /^[a-z]/ ? camelize $name : $name;
29 2         4 my @classes = map {"${_}::$suffix"} @{$self->signature_namespaces};
  2         9  
  2         11  
30 2 100       6 for my $class (@classes, $name) { return $class->new if _load($class) }
  3         8  
31 1         14 return Mojo::UserAgent::Signature::None->new;
32             }
33              
34             sub _load {
35 3     3   7 my $module = shift;
36 3 100       11 return $module->isa('Mojo::UserAgent::Signature::Base')
37             unless my $e = load_class $module;
38 2 50       850 ref $e ? die $e : return undef;
39             }
40              
41             1;
42              
43             =encoding utf8
44              
45             =head1 NAME
46              
47             Mojo::UserAgent::Role::Signature - Role for Mojo::UserAgent that automatically
48             signs request transactions
49              
50             =head1 SYNOPSIS
51              
52             use Mojo::UserAgent;
53              
54             my $ua = Mojo::UserAgent->with_roles('+Signature')->new;
55             $ua->initialize_signature(SomeService => {%args});
56             my $tx = $ua->get('/api/for/some/service');
57             say $tx->req->headers->authorization;
58              
59             =head1 DESCRIPTION
60              
61             L is a role for the full featured non-blocking
62             I/O HTTP and WebSocket user agent L, that automatically signs
63             request transactions.
64              
65             This module modifies the L by wrapping L
66             the L method with L signing the
67             final built transaction using the object instance set in the L
68             attribute that is this module adds to the L class.
69              
70             =head1 ATTRIBUTES
71              
72             =head2 signature
73              
74             $signature = $ua->signature;
75             $ua = $ua->signature(SomeService->new);
76              
77             If this attribute is not defined, the method modifier provided by this
78             L will have no effect on the transaction being built
79             by L.
80              
81             =head2 signature_namespaces
82              
83             $namespaces = $ua->signature_namespaces;
84             $ua = $ua->signature_namespaces(['Mojo::UserAgent::Signature']);
85              
86             Namespaces to load signature from, defaults to C.
87              
88             # Add another namespace to load signature from
89             push @{$ua->namespaces}, 'MyApp::Signature';
90              
91             =head1 METHODS
92              
93             L inherits all methods from L and
94             implements the following new ones.
95              
96             =head2 initialize_signature
97              
98             $ua->initialize_signature('some_service');
99             $ua->initialize_signature('some_service', foo => 23);
100             $ua->initialize_signature('some_service', {foo => 23});
101             $ua->initialize_signature('SomeService');
102             $ua->initialize_signature('SomeService', foo => 23);
103             $ua->initialize_signature('SomeService', {foo => 23});
104             $ua->initialize_signature('MyApp::Signature::SomeService');
105             $ua->initialize_signature('MyApp::Signature::SomeService', foo => 23);
106             $ua->initialize_signature('MyApp::Signature::SomeService', {foo => 23});
107              
108             Load a signature from the configured namespaces or by full module name and run
109             init, optional arguments are passed through.
110              
111             =head2 load_signature
112              
113             my $signature = $ua->load_signature('some_service');
114             my $signature = $ua->load_signature('SomeService');
115             my $signature = $ua->load_signature('MyApp::Signature::SomeService');
116              
117             Load a signature from the configured namespaces or by full module name. Will
118             fallback to L if the specified signature
119             cannot be loaded.
120              
121             =head1 COPYRIGHT AND LICENSE
122              
123             Copyright (C) 2020, Stefan Adams.
124              
125             This program is free software, you can redistribute it and/or modify it under
126             the terms of the Artistic License version 2.0.
127              
128             =head1 SEE ALSO
129              
130             L, L.
131              
132             =cut