File Coverage

lib/Net/Upwork/API/Client.pm
Criterion Covered Total %
statement 48 95 50.5
branch 0 6 0.0
condition 0 2 0.0
subroutine 16 26 61.5
pod 10 10 100.0
total 74 139 53.2


line stmt bran cond sub pod time code
1             # Licensed under the Upwork's API Terms of Use;
2             # you may not use this file except in compliance with the Terms.
3             #
4             # Unless required by applicable law or agreed to in writing, software
5             # distributed under the License is distributed on an "AS IS" BASIS,
6             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7             # See the License for the specific language governing permissions and
8             # limitations under the License.
9             #
10             # Author:: Maksym Novozhylov (mnovozhilov@upwork.com)
11             # Copyright:: Copyright 2015(c) Upwork.com
12             # License:: See LICENSE.txt and TOS - https://developers.upwork.com/api-tos.html
13              
14             package Net::Upwork::API::Client;
15              
16 33     33   227 use strict;
  33         56  
  33         983  
17 33     33   152 use warnings;
  33         66  
  33         903  
18              
19 33     33   16869 use Net::OAuth2::Profile::WebServer;
  33         2848740  
  33         1395  
20 33     33   29237 use IO::Socket::SSL qw( SSL_VERIFY_NONE );
  33         2870243  
  33         262  
21 33     33   3414 use LWP::UserAgent;
  33         74  
  33         1125  
22              
23 33     33   194 use constant BASE_HOST => "https://www.upwork.com";
  33         79  
  33         1971  
24 33     33   242 use constant DEFAULT_EPOINT => "api";
  33         88  
  33         1637  
25 33     33   213 use constant GRAPHQL_EPOINT => "https://api.upwork.com/graphql";
  33         74  
  33         1445  
26              
27 33     33   187 use constant DATA_FORMAT => "json";
  33         72  
  33         1397  
28 33     33   197 use constant OVERLOAD_VAR => "http_method";
  33         60  
  33         2562  
29              
30 33     33   240 use constant URI_AUTH => "/ab/account-security/oauth2/authorize";
  33         51  
  33         1743  
31 33     33   190 use constant URI_ATOKEN => "/api/v3/oauth2/token";
  33         64  
  33         1364  
32              
33 33     33   171 use constant ENTRY_POINT_API => "api";
  33         61  
  33         1557  
34 33     33   677 use constant ENTRY_POINT_GDS => "gds";
  33         97  
  33         1908  
35 33     33   254 use constant ENTRY_POINT_GQL => "graphql";
  33         63  
  33         1771  
36              
37 33     33   222 use constant UPWORK_LIBRARY_USER_AGENT => "Github Upwork API Perl Client";
  33         45  
  33         31156  
38              
39             our $lwp;
40              
41             =pod
42              
43             =head1 NAME
44              
45             Client
46              
47             =head1 FUNCTIONS
48              
49             =over 4
50              
51             =item new($config)
52              
53             Create a new Client
54              
55             B
56              
57             $config
58              
59             Config object
60              
61             =cut
62              
63             sub new {
64 0     0 1   my $class = shift;
65 0           my $config = shift;
66 0           my %opts = @_;
67 0           $opts{config} = $config;
68 0           my $self = bless \%opts, $class;
69              
70 0           $self->get_oauth_client();
71              
72 0           return $self;
73             }
74              
75             =item get_oauth_client
76              
77             Initialize OAuth client
78              
79             =cut
80              
81             sub get_oauth_client {
82 0     0 1   my $self = shift;
83              
84 0           $lwp = LWP::UserAgent->new();
85 0           $lwp->agent(UPWORK_LIBRARY_USER_AGENT);
86              
87 0 0         if ($self->{config}{grant_type} eq "client_credentials") {
88             $self->{oauth_client} = Net::OAuth2::Profile::WebServer->new(
89             client_id => $self->{config}{client_id},
90             client_secret => $self->{config}{client_secret},
91             grant_type => $self->{config}{grant_type},
92             access_token => $self->{config}{access_token},
93             expires_in => $self->{config}{expires_in},
94             expires_at => $self->{config}{expires_at},
95             site => BASE_HOST,
96             access_token_path => URI_ATOKEN,
97             redirect_uri => $self->{config}{redirect_uri},
98 0           user_agent => $lwp
99             );
100             } else {
101             $self->{oauth_client} = Net::OAuth2::Profile::WebServer->new(
102             client_id => $self->{config}{client_id},
103             client_secret => $self->{config}{client_secret},
104             access_token => $self->{config}{access_token},
105             refresh_token => $self->{config}{refresh_token},
106             expires_in => $self->{config}{expires_in},
107             expires_at => $self->{config}{expires_at},
108             site => BASE_HOST,
109             authorize_path => URI_AUTH,
110             access_token_path => URI_ATOKEN,
111             refresh_token_path => URI_ATOKEN,
112             redirect_uri => $self->{config}{redirect_uri},
113 0           user_agent => $lwp
114             );
115             }
116             }
117              
118             =item get
119              
120             GET request to protected resource
121              
122             B
123              
124             $uri
125              
126             Resource URL
127              
128             $params
129              
130             Hash of parameters
131              
132             B
133              
134             String
135              
136             =cut
137              
138             sub get {
139 0     0 1   my $self = shift;
140 0           my $uri = shift;
141 0           my %params = @_;
142              
143 0           return $self->send_request($uri, "GET", \%params);
144             }
145              
146             =item post
147              
148             POST request to protected resource
149              
150             B
151              
152             $uri
153              
154             Resource URL
155              
156             $params
157              
158             Hash of parameters
159              
160             B
161              
162             String
163              
164             =cut
165              
166             sub post {
167 0     0 1   my $self = shift;
168 0           my $uri = shift;
169 0           my %params = @_;
170              
171 0           return $self->send_request($uri, "POST", \%params);
172             }
173              
174             =item put
175              
176             PUT request to protected resource
177              
178             B
179              
180             $uri
181              
182             Resource URL
183              
184             $params
185              
186             Hash of parameters
187              
188             B
189              
190             String
191              
192             =cut
193              
194             sub put {
195 0     0 1   my $self = shift;
196 0           my $uri = shift;
197 0           my %params = @_;
198              
199 0           $params{&OVERLOAD_VAR} = 'put';
200              
201 0           return $self->send_request($uri, "POST", \%params);
202             }
203              
204             =item delete
205              
206             DELETE request to protected resource
207              
208             B
209              
210             $uri
211              
212             Resource URL
213              
214             $params
215              
216             Hash of parameters
217              
218             B
219              
220             String
221              
222             =cut
223              
224             sub delete {
225 0     0 1   my $self = shift;
226 0           my $uri = shift;
227 0           my %params = @_;
228              
229 0           $params{&OVERLOAD_VAR} = 'delete';
230              
231 0           return $self->send_request($uri, "POST", \%params);
232             }
233              
234             =item send_request
235              
236             Send a signed OAuth request to a specific protected resource
237              
238             B
239              
240             $uri
241              
242             Resource URI
243              
244             $method
245              
246             Request method
247              
248             $params
249              
250             API parameters
251              
252             B
253              
254             String, a response content
255              
256             =cut
257              
258             sub send_request {
259 0     0 1   my ($self, $uri, $method, $params) = @_;
260              
261 0           my $_method = lc $method;
262 0           my $response = $self->{access_token_session}->$_method($self->{oauth_client}->site_url(format_uri($uri, $self->{epoint}), %$params));
263              
264 0           return $response->decoded_content;
265             }
266              
267             =item graphql_request
268              
269             Send a signed GraphQL request to a specific OAuth2 protected resource
270              
271             B
272              
273             $params
274              
275             API parameters
276              
277             B
278              
279             String, a response content
280              
281             =cut
282              
283             sub graphql_request {
284 0     0 1   my ($self, $json, $tenant_id) = @_;
285              
286 0           my $req = HTTP::Request->new('POST', GRAPHQL_EPOINT);
287             $req->header(
288             'Content-Type' => 'application/json',
289 0           'Authorization' => sprintf("%s %s", $self->{access_token_session}->token_type(), $self->{access_token_session}->access_token())
290             );
291 0 0         if (defined($tenant_id)) {
292 0           $req->header('X-Upwork-API-TenantId' => $tenant_id);
293             }
294 0           $req->content($json);
295              
296 0           my $res = $lwp->request($req);
297              
298 0           return $res->decoded_content;
299             }
300              
301             =item format_uri
302              
303             Create a path to a specific resource
304              
305             B
306              
307             $uri
308              
309             URI to the protected resource
310              
311             $epoint
312              
313             Specific epoint
314              
315             B
316              
317             String
318              
319             =cut
320              
321             sub format_uri {
322 0     0 1   my ($uri, $epoint) = @_;
323 0   0       $epoint ||= DEFAULT_EPOINT;
324              
325 0 0         return $epoint . $uri . (($epoint eq DEFAULT_EPOINT) ? "." . DATA_FORMAT : "");
326             }
327              
328             =item version
329              
330             Get version of native OAuth client
331              
332             =cut
333              
334             sub version {
335 0     0 1   return $Net::OAuth::VERSION;
336             }
337              
338             =back
339              
340             =head1 AUTHOR
341              
342             Maksym Novozhylov C<< >>
343              
344             =head1 COPYRIGHT
345              
346             Copyright E Upwork Global Corp., 2018
347              
348             =cut
349              
350             1;