File Coverage

blib/lib/HTTP/Proxy/FilterStack.pm
Criterion Covered Total %
statement 73 74 98.6
branch 16 18 88.8
condition 6 8 75.0
subroutine 12 12 100.0
pod 10 10 100.0
total 117 122 95.9


line stmt bran cond sub pod time code
1             package HTTP::Proxy::FilterStack;
2             $HTTP::Proxy::FilterStack::VERSION = '0.302';
3             # Here's a description of the class internals
4             # - filters: the list of (sub, filter) pairs that match the message,
5             # and through which it must go
6             # - current: the actual list of filters, which is computed during
7             # the first call to filter()
8             # - buffers: the buffers associated with each (selected) filter
9             # - body : true if it's a HTTP::Proxy::BodyFilter stack
10              
11 66     66   274 use strict;
  66         86  
  66         2011  
12 66     66   268 use Carp;
  66         80  
  66         45847  
13              
14             # new( $isbody )
15             # $isbody is true only for response-body filters stack
16             sub new {
17 238     238 1 998 my $class = shift;
18 238   100     1193 my $self = {
19             body => shift || 0,
20             filters => [],
21             buffers => [],
22             current => undef,
23             };
24 238 100       589 $self->{type} = $self->{body} ? "HTTP::Proxy::BodyFilter"
25             : "HTTP::Proxy::HeaderFilter";
26 238         837 return bless $self, $class;
27             }
28              
29             #
30             # insert( $index, [ $matchsub, $filter ], ...)
31             #
32             sub insert {
33 3     3 1 1412 my ( $self, $idx ) = ( shift, shift );
34 3   66     394 $_->[1]->isa( $self->{type} ) or croak("$_ is not a $self->{type}") for @_;
35 1         1 splice @{ $self->{filters} }, $idx, 0, @_;
  1         4  
36             }
37              
38             #
39             # remove( $index )
40             #
41             sub remove {
42 1     1 1 2 my ( $self, $idx ) = @_;
43 1         1 splice @{ $self->{filters} }, $idx, 1;
  1         5  
44             }
45              
46             #
47             # push( [ $matchsub, $filter ], ... )
48             #
49             sub push {
50 152     152 1 757 my $self = shift;
51 152   66     1552 $_->[1]->isa( $self->{type} ) or croak("$_ is not a $self->{type}") for @_;
52 150         203 push @{ $self->{filters} }, @_;
  150         400  
53             }
54              
55 5     5 1 9 sub all { return @{ $_[0]->{filters} }; }
  5         34  
56 82     82 1 475 sub will_modify { return $_[0]->{will_modify}; }
57              
58             #
59             # select the filters that will be used on the message
60             #
61             sub select_filters {
62 307     307 1 8451 my ($self, $message ) = @_;
63              
64             # first time we're called this round
65 307 100       1002 if ( not defined $self->{current} ) {
66              
67             # select the filters that match
68 166         692 $self->{current} =
69 300         437 [ map { $_->[1] } grep { $_->[0]->() } @{ $self->{filters} } ];
  166         795  
  300         910  
70              
71             # create the buffers
72 300 100       889 if ( $self->{body} ) {
73 152         351 $self->{buffers} = [ ( "" ) x @{ $self->{current} } ];
  152         612  
74 152         323 $self->{buffers} = [ \( @{ $self->{buffers} } ) ];
  152         328  
75             }
76              
77             # start the filter if needed (and pass the message)
78 300         429 for ( @{ $self->{current} } ) {
  300         773  
79 166 100       2934 if ( $_->can('begin') ) { $_->begin( $message ); }
  3 50       25  
80             elsif ( $_->can('start') ) {
81 0         0 $_->proxy->log( HTTP::Proxy::ERROR(), "DEPRECATION", "The start() filter method is *deprecated* and disappeared in 0.15!\nUse begin() in your filters instead!" );
82             }
83             }
84              
85             # compute the "will_modify" value
86 15         51 $self->{will_modify} = $self->{body}
87 300 100       2182 ? grep { $_->will_modify() } @{ $self->{current} }
  152         637  
88             : 0;
89             }
90             }
91              
92             #
93             # the actual filtering is done here
94             #
95             sub filter {
96 293     293 1 4408 my $self = shift;
97              
98             # pass the body data through the filter
99 293 100       801 if ( $self->{body} ) {
100 145         208 my $i = 0;
101 145         247 my ( $data, $message, $protocol ) = @_;
102 145         195 for ( @{ $self->{current} } ) {
  145         541  
103 21         41 $$data = ${ $self->{buffers}[$i] } . $$data;
  21         66  
104 21         24 ${ $self->{buffers}[ $i ] } = "";
  21         42  
105 21         76 $_->filter( $data, $message, $protocol, $self->{buffers}[ $i++ ] );
106             }
107             }
108             else {
109 148         263 $_->filter(@_) for @{ $self->{current} };
  148         1348  
110 148         1761 $self->eod;
111             }
112             }
113              
114             #
115             # filter what remains in the buffers
116             #
117             sub filter_last {
118 75     75 1 788 my $self = shift;
119 75 50       288 return unless $self->{body}; # sanity check
120              
121 75         161 my $i = 0;
122 75         154 my ( $data, $message, $protocol ) = @_;
123 75         120 for ( @{ $self->{current} } ) {
  75         250  
124 5         11 $$data = ${ $self->{buffers}[ $i ] } . $$data;
  5         15  
125 5         6 ${ $self->{buffers}[ $i++ ] } = "";
  5         17  
126 5         17 $_->filter( $data, $message, $protocol, undef );
127             }
128              
129             # call the cleanup routine if needed
130 75 100       568 for ( @{ $self->{current} } ) { $_->end if $_->can('end'); }
  75         336  
  5         29  
131            
132             # clean up the mess for next time
133 75         431 $self->eod;
134             }
135              
136             #
137             # END OF DATA cleanup method
138             #
139             sub eod {
140 298     298 1 741 $_[0]->{buffers} = [];
141 298         916 $_[0]->{current} = undef;
142             }
143              
144             1;
145              
146             __END__