File Coverage

blib/lib/Plack/Middleware/Matomo.pm
Criterion Covered Total %
statement 64 68 94.1
branch 11 16 68.7
condition 3 6 50.0
subroutine 11 12 91.6
pod 1 1 100.0
total 90 103 87.3


line stmt bran cond sub pod time code
1             package Plack::Middleware::Matomo;
2              
3             our $VERSION = '0.10';
4              
5 1     1   54425 use strict;
  1         10  
  1         25  
6 1     1   4 use warnings;
  1         2  
  1         22  
7 1     1   514 use AnyEvent::HTTP;
  1         29184  
  1         72  
8 1     1   468 use Log::Any '$log';
  1         8415  
  1         5  
9 1     1   2182 use Plack::Request;
  1         60843  
  1         39  
10             use Plack::Util::Accessor
11 1     1   382 qw(apiv base_url idsite token_auth time_format oai_identifier_format view_paths download_paths ua urlref);
  1         228  
  1         6  
12 1     1   86 use URI;
  1         2  
  1         18  
13              
14 1     1   5 use parent 'Plack::Middleware';
  1         2  
  1         6  
15              
16             sub call {
17 3     3 1 21961 my ($self, $env) = @_;
18              
19 3         18 my $request = Plack::Request->new($env);
20 3         34 my $res = $self->app->($env);
21              
22             # only get requests
23 3 50       316 return $res unless $request->method =~ m{^get$}i;
24              
25 3         30 my ($action, $id);
26 3         13 my $view_paths = $self->view_paths;
27 3         17 my $download_paths = $self->download_paths;
28              
29 3         17 $log->info("Entering Matomo middleware at " . $request->path);
30              
31 3         33 foreach my $p (@$view_paths) {
32 3 100       18 if ($request->path =~ /$p/) {
33 1         19 $id = $1;
34 1         8 $action = "view";
35 1         2 last;
36             }
37             }
38 3         17 foreach my $p (@$download_paths) {
39 3 100       5 if ($request->path =~ /$p/) {
40 1         9 $id = $1;
41 1         2 $action = "download";
42 1         1 last;
43             }
44             }
45              
46 3 100       27 return $res unless $action;
47 2         8 $log->info("Action: $action");
48              
49 2   50     10 my $time_format = $self->time_format // '%Y-%m-%dT%H:%M:%SZ';
50 2         17 my $ip = $self->_anonymize_ip($request->address);
51 2         6 my $oai_id = sprintf($self->oai_identifier_format, $id);
52 2         52 my $cvar = '{"1":["oaipmhID","' . $oai_id . '"]}';
53              
54 2         6 my $rand = int(rand(10000));
55              
56 2   50     8 my $event = {
      50        
57             _id => $request->session // '',
58             action_name => $action,
59             apiv => $self->apiv // 1,
60             cvar => $cvar,
61             idsite => $self->idsite,
62             rand => $rand,
63             rec => 1,
64             token_auth => $self->token_auth,
65             url => $request->uri,
66             visitIP => $ip,
67             };
68              
69 2 50       623 $event->{ua} = $request->user_agent if $self->ua;
70 2 50       14 $event->{urlref} = $request->referer if $self->urlref;
71              
72 2 100       11 if ($action eq 'download') {
73 1         3 $event->{download} = $request->uri;
74             }
75              
76 2         170 $self->_push_to_matomo($event);
77              
78 2         18461 return $res;
79             }
80              
81             sub _anonymize_ip {
82 2     2   15 my ($self, $ip) = @_;
83              
84 2         10 $ip =~ s/\.\d+?$/\.0/;
85              
86 2         5 return $ip;
87             }
88              
89             sub _push_to_matomo {
90 2     2   5 my ($self, $event) = @_;
91              
92 2         6 my $uri = URI->new($self->base_url);
93 2         111 $uri->query_form($event);
94              
95 2         807 $log->debug("URL: " . $uri->as_string);
96              
97             http_head $uri->as_string, sub {
98 0     0     my ($body, $hdr) = @_;
99              
100 0 0         if ($hdr->{Status} =~ /^2/) {
101 0           $log->debug("Ok matomo endpoint: $hdr->{Status} $hdr->{Reason} for " . $uri->as_string);
102             } else {
103 0           $log->error("Could not reach matomo endpoint: $hdr->{Status} $hdr->{Reason} for " . $uri->as_string);
104             }
105 2         24 };
106             }
107              
108             1;
109              
110             __END__