File Coverage

blib/lib/PITA/Guest/Server/HTTP.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package PITA::Guest::Server::HTTP;
2              
3             # The HTTP server component of the support server
4              
5 1     1   2861 use 5.008;
  1         5  
  1         52  
6 1     1   8 use strict;
  1         3  
  1         81  
7 1     1   8 use File::Spec ();
  1         3  
  1         25  
8 1     1   664 use POE::Declare::HTTP::Server 0.05 ();
  0            
  0            
9              
10             our $VERSION = '0.60';
11             our @ISA = 'POE::Declare::HTTP::Server';
12              
13             use POE::Declare {
14             Mirrors => 'Param',
15             PingEvent => 'Message',
16             MirrorEvent => 'Message',
17             UploadEvent => 'Message',
18             };
19              
20              
21              
22              
23              
24             ######################################################################
25             # Constructor and Accessors
26              
27             sub new {
28             my $self = shift->SUPER::new(
29             Mirrors => { },
30             @_,
31             Handler => sub {
32             # Convert to a more convention form
33             $_[0]->handler( $_[1]->request, $_[1] );
34             },
35             );
36              
37             # Check and normalize
38             unless ( Params::Util::_HASH0($self->Mirrors) ) {
39             die "Missing or invalid Mirrors param";
40             }
41             foreach my $route ( sort keys %{$self->Mirrors} ) {
42             my $dir = File::Spec->rel2abs( $self->Mirrors->{$route} );
43             unless ( -d $dir ) {
44             die "Directory '$dir' for mirror '$route' does not exist";
45             }
46             $self->Mirrors->{$route} = $dir;
47             }
48              
49             return $self;
50             }
51              
52              
53              
54              
55              
56             ######################################################################
57             # Main Methods
58              
59             # Sort of half-assed Process compatibility for testing purposes
60             sub run {
61             $_[0]->start;
62             POE::Kernel->run;
63             return 1;
64             }
65              
66             # Wrapper for doing cleansing of the response
67             sub handler {
68             my $self = shift;
69             my $response = $_[1];
70              
71             # Call the main handler
72             $self->_handler(@_);
73              
74             # Add content length for all responses
75             if ( defined $response->content ) {
76             unless ( $response->header('Content-Length') ) {
77             my $bytes = length $response->content;
78             $response->header( 'Content-Length' => $bytes );
79             }
80             }
81              
82             return;
83             }
84              
85             sub _handler {
86             my $self = shift;
87             my $request = shift;
88             my $response = shift;
89             my $path = $request->uri->path;
90              
91             if ( $request->method eq 'GET' ) {
92             # Handle a ping
93             if ( $path eq '/' ) {
94             $response->code(200);
95             $response->header( 'Content-Type' => 'text/plain' );
96             $response->content('200 - PONG');
97             $self->PingEvent;
98             return;
99             }
100              
101             # Handle a mirror file fetch
102             my $Mirrors = $self->Mirrors;
103             foreach my $route ( sort keys %$Mirrors ) {
104             my $escaped = quotemeta $route;
105             next unless $path =~ /^$escaped(.+)$/;
106             my $file = $1;
107             my $root = $Mirrors->{$route};
108             my $full = File::Spec->catfile( $root, $file );
109             if ( -f $full and -r _ ) {
110             # Load the file
111             local $/ = undef;
112             my $io = IO::File->new($full, 'r') or die "open: $full";
113             $io->binmode;
114             my $blob = $io->getline;
115              
116             # Send the file
117             $response->code(200);
118             $response->header('Content-Type' => 'application/x-gzip');
119             $response->content($blob);
120             } else {
121             $response->code(404);
122             $response->header('Content-Type' => 'text/plain');
123             $response->content('404 - File Not Found');
124             }
125              
126             # Report the mirror event
127             $self->MirrorEvent( $route, $file, $response->code );
128              
129             return;
130             }
131             }
132              
133             if ( $request->method eq 'PUT' ) {
134             # Send the upload message
135             $self->UploadEvent( $path => \( $request->content ) );
136              
137             # Send a content-less ok to the client
138             $response->code(204);
139             $response->message('Upload received');
140              
141             return;
142             }
143              
144             return;
145             }
146              
147             compile;