File Coverage

blib/lib/WWW/Gitea/Role/HTTP.pm
Criterion Covered Total %
statement 55 71 77.4
branch 13 26 50.0
condition 7 23 30.4
subroutine 11 13 84.6
pod 2 2 100.0
total 88 135 65.1


line stmt bran cond sub pod time code
1             package WWW::Gitea::Role::HTTP;
2              
3             # ABSTRACT: HTTP + token/basic auth role for the Gitea REST API
4              
5 5     5   3174 use Moo::Role;
  5         12  
  5         38  
6 5     5   2591 use Carp qw(croak);
  5         14  
  5         546  
7 5     5   8131 use JSON::MaybeXS qw(decode_json encode_json);
  5         40720  
  5         385  
8 5     5   1935 use HTTP::Request;
  5         53597  
  5         169  
9 5     5   2262 use HTTP::Request::Common ();
  5         12563  
  5         155  
10 5     5   3547 use LWP::UserAgent;
  5         126155  
  5         287  
11 5     5   1630 use MIME::Base64 qw(encode_base64);
  5         2512  
  5         390  
12 5     5   31 use URI;
  5         7  
  5         162  
13 5     5   22 use Log::Any qw($log);
  5         9  
  5         42  
14              
15              
16             requires 'api_url';
17             requires 'token';
18             requires 'username';
19             requires 'password';
20              
21             has ua => (
22             is => 'lazy',
23             builder => sub {
24 0   0 0   0 LWP::UserAgent->new(
25             agent => 'WWW-Gitea/' . ($WWW::Gitea::VERSION // 'dev'),
26             timeout => 30,
27             );
28             },
29             );
30              
31              
32             sub _apply_auth {
33 8     8   10890 my ($self, $req) = @_;
34 8 100 66     89 if (defined $self->token && length $self->token) {
    50 33        
35 7         60 $req->header(Authorization => 'token ' . $self->token);
36             }
37             elsif (defined $self->username && defined $self->password) {
38 1         16 $req->header(Authorization => 'Basic '
39             . encode_base64($self->username . ':' . $self->password, ''));
40             }
41 8         731 return;
42             }
43              
44             sub request {
45 6     6 1 32 my ($self, $method, $path, %args) = @_;
46              
47 6         173 my $uri = URI->new($self->api_url . $path);
48 6 50       25891 $uri->query_form($args{query}) if $args{query};
49              
50 6         993 my $req;
51 6 100       28 if (my $up = $args{upload}) {
52 2   50     10 my $field = $up->{field} || 'attachment';
53             my $value = defined $up->{file}
54             ? [ $up->{file}, $up->{filename} ]
55 2 100 50     13 : [ undef, $up->{filename}, Content => ($up->{content} // '') ];
56 2         12 $req = HTTP::Request::Common::POST(
57             "$uri",
58             Content_Type => 'form-data',
59             Content => [ $field => $value ],
60             );
61 2         24412 $req->method($method);
62             }
63             else {
64 4         32 $req = HTTP::Request->new($method => $uri);
65             }
66 6         440 $self->_apply_auth($req);
67 6         28 $req->header(Accept => 'application/json');
68 6 50       312 for my $k (keys %{ $args{headers} || {} }) {
  6         77  
69 0         0 $req->header($k => $args{headers}{$k});
70             }
71              
72 6 50       27 if (defined $args{body}) {
73 0   0     0 my $ct = $args{content_type} || 'application/json';
74 0         0 $req->header('Content-Type' => $ct);
75 0 0       0 $req->content(ref $args{body} ? encode_json($args{body}) : $args{body});
76             }
77              
78 6         98 $log->debugf('Gitea %s %s', $method, $uri);
79 6         251 my $res = $self->ua->request($req);
80              
81 6         929 my $body = $res->decoded_content;
82 6         1174 my $data;
83 6 50 33     75 if (defined $body && length $body && $body =~ /\A\s*[\{\[]/) {
      33        
84 6         61 $data = decode_json($body);
85             }
86              
87 6 50       32 unless ($res->is_success) {
88             my $msg = ref $data eq 'HASH'
89 0 0 0     0 ? ($data->{message} || $data->{error} || $res->status_line)
90             : $res->status_line;
91 0         0 $log->errorf('Gitea API error: %s', $msg);
92 0         0 croak "Gitea API error ($method $path): $msg";
93             }
94              
95             # 204 No Content (deletes etc.) — no body to decode
96 6 50       154 return defined $data ? $data : 1;
97             }
98              
99              
100             sub request_status {
101 0     0 1   my ($self, $method, $path, %args) = @_;
102 0           my $uri = URI->new($self->api_url . $path);
103 0 0         $uri->query_form($args{query}) if $args{query};
104 0           my $req = HTTP::Request->new($method => $uri);
105 0           $self->_apply_auth($req);
106 0           $req->header(Accept => 'application/json');
107 0           $log->debugf('Gitea %s %s (status only)', $method, $uri);
108 0           return $self->ua->request($req)->code;
109             }
110              
111              
112              
113             1;
114              
115             __END__