File Coverage

blib/lib/Plack/Middleware/MonocerosStatus.pm
Criterion Covered Total %
statement 35 63 55.5
branch 6 26 23.0
condition 0 6 0.0
subroutine 7 10 70.0
pod 2 3 66.6
total 50 108 46.3


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