File Coverage

blib/lib/Plack/App/CLI.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package Plack::App::CLI;
2              
3 1     1   24599 use strict;
  1         3  
  1         40  
4 1     1   5 use warnings;
  1         1  
  1         45  
5              
6             our $VERSION = '0.1';
7              
8 1     1   2840 use Getopt::Std;
  1         61  
  1         70  
9 1     1   502697 use Term::ANSIColor;
  1         12569  
  1         81  
10 1     1   1058 use IO::Handle;
  1         7678  
  1         53  
11 1     1   997 use URI;
  1         9731  
  1         34  
12              
13 1     1   449 use Plack;
  0            
  0            
14             use Plack::TempBuffer;
15             use Plack::Util;
16              
17             my $colors = 1;
18             my $output = IO::Handle->new_from_fd(fileno(STDOUT), "w");
19             my $error = IO::Handle->new_from_fd(fileno(STDERR), "w");
20             my $headers = 0;
21              
22             use constant {
23             STATUS => 0,
24             HEADERS => 1,
25             BODY => 2
26             };
27              
28             my $env = {
29             HTTP_ACCEPT => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
30             HTTP_USER_AGENT => "Plack $Plack::VERSION, CLI $VERSION",
31             HTTP_CACHE_CONTROL => 'max-age=0',
32             HTTP_ACCEPT_LANGUAGE => 'en-US,en;q=0.8',
33             HTTP_ACCEPT_ENCODING => 'gzip,deflate,sdch',
34             HTTP_ACCEPT_CHARSET => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
35              
36             # Client
37             REQUEST_METHOD => 'GET',
38             SCRIPT_NAME => '',
39             REMOTE_ADDR => '0.0.0.0',
40             REMOTE_USER => $ENV{USER},
41              
42             # Server
43             SERVER_PROTOCOL => 'HTTP/1.0',
44             SERVER_PORT => 0,
45             SERVER_NAME => 'localhost',
46              
47             # PSGI
48             'psgi.version' => [1,1],
49             'psgi.errors' => $error,
50             'psgi.multithread' => Plack::Util::FALSE,
51             'psgi.multiprocess' => Plack::Util::TRUE,
52             'psgi.run_once' => Plack::Util::TRUE,
53             'psgi.streaming' => Plack::Util::FALSE,
54             'psgi.nonblocking' => Plack::Util::FALSE,
55              
56             %ENV
57             };
58              
59             sub run {
60             my($self, $app) = @_;
61              
62             if ( ref $app ne "CODE" ) {
63             $app = Plack::Util::load_psgi($app);
64             }
65            
66             my $options = {};
67             my $environment = "deployment";
68              
69             getopts("E:X:o:H:vnh", $options);
70              
71             if ( exists $options->{E} ) {
72             $environment = $options->{E};
73             }
74              
75             if ( $options->{v} ) {
76             print $env->{HTTP_USER_AGENT}, "\n";
77             exit(0);
78             }
79              
80             if ( $options->{n} ) {
81             $colors = 0;
82             }
83              
84             if ( $options->{h} ) {
85             $headers = 1;
86             }
87              
88             my $method = "GET";
89              
90             my $request_uri = ( shift @ARGV || "/" );
91             my $url = "http://localhost" . $request_uri;
92              
93             if ( exists $options->{X} ) {
94             $method = $options->{X};
95             }
96              
97             if ( exists $options->{o} ) {
98             $output = new IO::File "> $options->{o}";
99             $colors = 0;
100             }
101              
102             if ( $method eq "POST" ) {
103             my $data = "";
104             while ( ) { chomp; $data .= $_; }
105              
106             my $len = length $data;
107             my $buf = new Plack::TempBuffer($len);
108             $buf->print($data);
109              
110             $env->{CONTENT_LENGTH} = $len;
111             $env->{CONTENT_TYPE} = "application/x-www-form-urlencoded";
112             $env->{'psgi.input'} = $buf->rewind;
113             } elsif ( $method eq "GET" ) {
114             $method = "GET";
115             } else {
116             print STDERR "Only GET and POST methods are supported.\n";
117             }
118              
119             $env->{environment} = $environment;
120            
121             my $uri = URI->new($url);
122              
123             $env->{REQUEST_METHOD} = $method;
124             $env->{REQUEST_URI} = $request_uri;
125             $env->{SCRIPT_NAME} = $uri->path;
126             $env->{SCRIPT_NAME} = '' if $env->{SCRIPT_NAME} eq '/';
127             $env->{QUERY_STRING} = $uri->query;
128             $env->{HTTP_HOST} = $uri->host;
129             $env->{PATH_INFO} = $uri->path;
130             $env->{'psgi.url_scheme'} = $uri->scheme;
131              
132             my $res = Plack::Util::run_app($app, $env);
133              
134             if (ref $res eq 'ARRAY') {
135             $self->_handle_response($res);
136             } elsif (ref $res eq 'CODE') {
137             $res->(sub {
138             $self->_handle_response($_[0]);
139             });
140             } else {
141             die "Bad response $res";
142             }
143             }
144              
145             sub _handle_response {
146             my ($self, $res) = @_;
147              
148             if ( $headers ) {
149             print "\n";
150              
151             print color "magenta bold" if $colors;
152             print "Request\n";
153             print " $env->{REQUEST_METHOD} $env->{REQUEST_URI} $env->{SERVER_PROTOCOL}\n";
154             print "\n";
155             print color "reset" if $colors;
156              
157             print color ( $res->[STATUS] == 200 ? "green bold" : "red" ) if $colors;
158             print "Response\n";
159             print " Status ", $res->[STATUS], " \n";
160             print color "reset" if $colors;
161              
162             print color "cyan bold" if $colors;
163             my %h = ( @{$res->[HEADERS]} );
164              
165             print " $_: $h{$_} \n" foreach keys %h;
166             print color "reset" if $colors;
167              
168             $output->print(color "reset") if $colors;
169             print "\n";
170             }
171              
172             if ( defined $res->[BODY] ) {
173             my $cb = sub { $output->print(@_); };
174             Plack::Util::foreach($res->[BODY], $cb);
175             }
176              
177             $output->close;
178             }
179              
180             1;
181             __END__