File Coverage

blib/lib/Plack/Middleware/MonocerosStatus.pm
Criterion Covered Total %
statement 57 63 90.4
branch 13 26 50.0
condition 2 6 33.3
subroutine 10 10 100.0
pod 2 3 66.6
total 84 108 77.7


line stmt bran cond sub pod time code
1             package Plack::Middleware::MonocerosStatus;
2              
3 9     9   7350 use strict;
  9         18  
  9         316  
4 9     9   45 use warnings;
  9         34  
  9         330  
5 9     9   52 use parent qw(Plack::Middleware);
  9         18  
  9         70  
6 9     9   2973 use Plack::Util::Accessor qw(path allow);
  9         18  
  9         76  
7 9     9   4954 use Net::CIDR::Lite;
  9         38749  
  9         367  
8 9     9   86 use IO::Socket::UNIX;
  9         18  
  9         168  
9              
10             sub prepare_app {
11 8     8 1 1072 my $self = shift;
12 8 50       48 if ( $self->allow ) {
13 8 50       440 my @ip = ref $self->allow ? @{$self->allow} : ($self->allow);
  8         72  
14 8         48 my @ipv4;
15             my @ipv6;
16 8         24 for (@ip) {
17             # hacky check, but actual checks are done in Net::CIDR::Lite.
18 16 100       72 if (/:/) {
19 8         32 push @ipv6, $_;
20             } else {
21 8         32 push @ipv4, $_;
22             }
23             }
24 8 50       32 if ( @ipv4 ) {
25 8         32 my $cidr4 = Net::CIDR::Lite->new();
26 8         128 $cidr4->add_any($_) for @ipv4;
27 8         2000 $self->{__cidr4} = $cidr4;
28             }
29 8 50       32 if ( @ipv6 ) {
30 8         32 my $cidr6 = Net::CIDR::Lite->new();
31 8         88 $cidr6->add_any($_) for @ipv6;
32 8         4456 $self->{__cidr6} = $cidr6;
33             }
34             }
35             }
36              
37             sub call {
38 1     1 1 75 my ($self, $env) = @_;
39 1 50 33     30 if( $self->path && $env->{PATH_INFO} eq $self->path ) {
40 1         47 return $self->_handle_status($env);
41             }
42 0         0 $self->app->($env);
43             }
44              
45             sub _handle_status {
46 1     1   7 my ($self, $env ) = @_;
47              
48 1 50       12 if ( ! $self->allowed($env->{REMOTE_ADDR}) ) {
49 0         0 return [403, ['Content-Type' => 'text/plain'], [ 'Forbidden' ]];
50             }
51            
52 1 50 33     274 if ( !$env->{X_MONOCEROS_WORKER_STATS} || ! -f $env->{X_MONOCEROS_WORKER_STATS}) {
53 0         0 return [500, ['Content-Type' => 'text/plain'], [ 'Monoceros stats file not found' ]];
54             }
55              
56 1 50       72 open(my $fh, $env->{X_MONOCEROS_WORKER_STATS}) or
57             return [500, ['Content-Type' => 'text/plain'], [ 'Could not open Monoceros stats: $!' ]];
58 1         69 my $len = $fh->sysread(my $buf, 1024);
59 1 50       25 if ( !$len ) {
60 0         0 return [500, ['Content-Type' => 'text/plain'], [ 'Could not read stats: $!' ]];
61             }
62 1         3 my %stats;
63 1         7 for my $str ( split /&/, $buf ) {
64 4         21 my ($key,$val) = split /=/, $str, 2;
65 4         36 $stats{$key} = $val;
66             }
67 1         6 my $msg = "Total: ".$stats{total}."\015\012";
68 1         3 $msg .= "Waiting: ".$stats{waiting}."\015\012";
69 1         5 $msg .= "Processing: ".$stats{processing}."\015\012";
70 1         4 $msg .= "MaxWorkers: ".$stats{max_workers}."\015\012\015\012";
71            
72 1         39 return [200, ['Content-Type' => 'text/plain'], [$msg]];
73             }
74              
75             sub allowed {
76 1     1 0 4 my ( $self , $address ) = @_;
77 1 50       12 if ( $address =~ /:/) {
78 0 0       0 return unless $self->{__cidr6};
79 0         0 return $self->{__cidr6}->find( $address );
80             }
81 1 50       6 return unless $self->{__cidr4};
82 1         19 return $self->{__cidr4}->find( $address );
83             }
84              
85              
86             1;
87              
88             __END__