File Coverage

blib/lib/LWP/Protocol/PSGI.pm
Criterion Covered Total %
statement 71 82 86.5
branch 21 28 75.0
condition n/a
subroutine 21 23 91.3
pod 4 6 66.6
total 117 139 84.1


line stmt bran cond sub pod time code
1             package LWP::Protocol::PSGI;
2              
3 3     3   116006 use strict;
  3         8  
  3         69  
4 3     3   64 use 5.008_001;
  3         12  
5             our $VERSION = '0.10';
6              
7 3     3   1135 use parent qw(LWP::Protocol);
  3         686  
  3         15  
8 3     3   28513 use HTTP::Message::PSGI qw( req_to_psgi res_from_psgi );
  3         26523  
  3         180  
9 3     3   23 use Carp;
  3         6  
  3         1210  
10              
11             my @protocols = qw( http https );
12             my %orig;
13              
14             my @apps;
15              
16             sub register {
17 18     18 1 4947 my $class = shift;
18              
19 18         67 my $app = LWP::Protocol::PSGI::App->new(@_);
20 18         39 unshift @apps, $app;
21              
22             # register this guy (as well as saving original code) once
23 18 100       49 if (! scalar keys %orig) {
24 2         6 for my $proto (@protocols) {
25 4 100       34 if (my $orig = LWP::Protocol::implementor($proto)) {
26 2         56755 $orig{$proto} = $orig;
27 2         9 LWP::Protocol::implementor($proto, $class);
28             } else {
29 2 50       581 Carp::carp("LWP::Protocol::$proto is unavailable. Skip registering overrides for it.") if $^W;
30             }
31             }
32             }
33              
34 18 50       69 if (defined wantarray) {
35             return LWP::Protocol::PSGI::Guard->new(sub {
36 18     18   66 $class->unregister_app($app);
37 18         90 });
38             }
39             }
40              
41             sub unregister_app {
42 18     18 0 38 my ($class, $app) = @_;
43              
44 18         28 my $i = 0;
45 18         35 foreach my $stored_app (@apps) {
46 18 50       48 if ($app == $stored_app) {
47 18         29 splice @apps, $i, 1;
48 18         89 return;
49             }
50 0         0 $i++;
51             }
52             }
53            
54              
55             sub unregister {
56 0     0 1 0 my $class = shift;
57 0         0 for my $proto (@protocols) {
58 0 0       0 if ($orig{$proto}) {
59 0         0 LWP::Protocol::implementor($proto, $orig{$proto});
60             }
61             }
62 0         0 @apps = ();
63             }
64              
65             sub request {
66 11     11 1 29021 my($self, $request, $proxy, $arg, @rest) = @_;
67              
68 11 50       28 if (my $app = $self->handles($request)) {
69 11         39 my $env = req_to_psgi $request;
70 11         7580 my $response = res_from_psgi $app->app->($env);
71 11         2099 my $content = $response->content;
72 11         129 $response->content('');
73 11         196 $self->collect_once($arg, $response, $content);
74             } else {
75 0         0 $orig{$self->{scheme}}->new($self->{scheme}, $self->{ua})->request($request, $proxy, $arg, @rest);
76             }
77             }
78              
79             # for testing
80             sub create {
81 0     0 1 0 my $class = shift;
82 0         0 push @apps, LWP::Protocol::PSGI::App->new(@_);
83 0         0 $class->new;
84             }
85              
86             sub handles {
87 22     22 0 1896 my($self, $request) = @_;
88              
89 22         44 foreach my $app (@apps) {
90 23 100       55 if ($app->match($request)) {
91 19         114 return $app;
92             }
93             }
94             }
95              
96             package
97             LWP::Protocol::PSGI::Guard;
98 3     3   20 use strict;
  3         9  
  3         193  
99              
100             sub new {
101 18     18   35 my($class, $code) = @_;
102 18         52 bless $code, $class;
103             }
104              
105             sub DESTROY {
106 18     18   9528 my $self = shift;
107 18         45 $self->();
108             }
109              
110             package
111             LWP::Protocol::PSGI::App;
112 3     3   15 use strict;
  3         7  
  3         716  
113              
114             sub new {
115 18     18   53 my ($class, $app, %options) = @_;
116 18         57 bless { app => $app, options => \%options }, $class;
117             }
118              
119 11     11   36 sub app { $_[0]->{app} }
120 23     23   52 sub options { $_[0]->{options} }
121             sub match {
122 23     23   37 my ($self, $request) = @_;
123 23         63 my $options = $self->options;
124              
125 23 100       63 if ($options->{host}) {
    100          
126 13         34 my $matcher = $self->_matcher($options->{host});
127 13 100       36 $matcher->($request->uri->host) || $matcher->($request->uri->host_port);
128             } elsif ($options->{uri}) {
129 4         11 $self->_matcher($options->{uri})->($request->uri);
130             } else {
131 6         16 1;
132             }
133             }
134              
135             sub _matcher {
136 17     17   53 my($self, $stuff) = @_;
137 17 100       66 if (ref $stuff eq 'Regexp') {
    100          
    50          
138 3     4   10 sub { $_[0] =~ $stuff };
  4         139  
139             } elsif (ref $stuff eq 'CODE') {
140 3         6 $stuff;
141             } elsif (!ref $stuff) {
142 11     14   39 sub { $_[0] eq $stuff };
  14         571  
143             } else {
144 0           Carp::croak("Don't know how to match: ", ref $stuff);
145             }
146             }
147              
148             1;
149             __END__