File Coverage

blib/lib/LWP/UserAgent/DNS/Hosts.pm
Criterion Covered Total %
statement 67 67 100.0
branch 14 18 77.7
condition 5 6 83.3
subroutine 19 19 100.0
pod 6 6 100.0
total 111 116 95.6


line stmt bran cond sub pod time code
1             package LWP::UserAgent::DNS::Hosts;
2              
3 5     5   624828 use 5.008001;
  5         51  
4 5     5   29 use strict;
  5         10  
  5         104  
5 5     5   23 use warnings;
  5         11  
  5         162  
6 5     5   27 use Carp;
  5         9  
  5         325  
7 5     5   1490 use LWP::Protocol;
  5         92542  
  5         196  
8 5     5   2317 use Scope::Guard qw(guard);
  5         2418  
  5         4548  
9              
10             our $VERSION = '0.14';
11             $VERSION = eval $VERSION;
12              
13             our @Protocols = qw(http https);
14             our %Implementors;
15              
16             our %Hosts;
17              
18             sub register_host {
19 15     15 1 5347 my ($class, $host, $peer_addr) = @_;
20 15         98 $Hosts{$host} = $peer_addr;
21             }
22              
23             sub register_hosts {
24 2     2 1 69201 my ($class, %pairs) = @_;
25 2         18 while (my ($host, $peer_addr) = each %pairs) {
26 4         12 $class->register_host($host, $peer_addr);
27             }
28             }
29              
30             sub clear_hosts {
31 6     6 1 16289 %Hosts = ();
32             }
33              
34             sub read_hosts {
35 3     3 1 6988 my ($class, $source) = @_;
36              
37 3 100 66     40 if (ref $source eq 'GLOB') {
    100          
38 1         4 $class->_read_hosts_from_handle($source);
39             }
40             elsif ($source !~ /[\x0D\x0A]/ && -f $source) {
41 1         6 $class->_read_hosts_from_file($source);
42             }
43             else {
44 1         4 $class->_read_hosts_from_string($source);
45             }
46             }
47              
48             sub _read_hosts_from_handle {
49 3     3   10 my ($class, $handle) = @_;
50 3         33 while (<$handle>) {
51 15         29 chomp;
52 15         30 s/^\s+//g;
53 15         40 s/\s+$//g;
54 15 100 100     96 next if !$_ || /^#/;
55              
56 6         34 my ($addr, @hosts) = split /\s+/;
57 6         13 for my $host (@hosts) {
58 9         23 $class->register_host($host, $addr);
59             }
60             }
61             }
62              
63             sub _read_hosts_from_file {
64 1     1   4 my ($class, $file) = @_;
65 1 50       35 open my $fh, '<', $file or croak $!;
66 1         8 $class->_read_hosts_from_handle($fh);
67 1         15 close $fh;
68             }
69              
70             sub _read_hosts_from_string {
71 1     1   3 my ($class, $string) = @_;
72 1 50   1   46 open my $fh, '<', \$string or croak $!;
  1         8  
  1         2  
  1         7  
73 1         818 $class->_read_hosts_from_handle($fh);
74 1         6 close $fh;
75             }
76              
77             sub _registered_peer_addr {
78 4     4   11 my ($class, $host) = @_;
79 4         18 return $Hosts{$host};
80             }
81              
82             sub _implementor {
83 1     1   5 my ($class, $proto) = @_;
84 1         25 return sprintf 'LWP::Protocol::%s::hosts' => $proto;
85             }
86              
87             sub enable_override {
88 1     1 1 9829 my $class = shift;
89              
90 1         32 for my $proto (@Protocols) {
91 2 100       60 if (my $orig = LWP::Protocol::implementor($proto)) {
92 1         12671 my $impl = $class->_implementor($proto);
93 1 50       113 if (eval "require $impl; 1") {
94 1         5 LWP::Protocol::implementor($proto => $impl);
95 1         32 $Implementors{$proto} = $orig;
96             }
97             }
98             else {
99 1         808 carp("LWP::Protocol::$proto is unavailable. Skip overriding it.");
100             }
101             }
102              
103 1 50       27 if (defined wantarray) {
104 1     1   42 return guard { $class->disable_override };
  1         268492  
105             }
106             }
107              
108             sub disable_override {
109 1     1 1 4 my $class = shift;
110 1         4 for my $proto (@Protocols) {
111 2 100       63 if (my $impl = $Implementors{$proto}) {
112 1         6 LWP::Protocol::implementor($proto, $impl);
113             }
114             }
115             }
116              
117             1;
118              
119             =encoding utf-8
120              
121             =for stopwords
122              
123             =head1 NAME
124              
125             LWP::UserAgent::DNS::Hosts - Override LWP HTTP/HTTPS request's host like /etc/hosts
126              
127             =head1 SYNOPSIS
128              
129             use LWP::UserAgent;
130             use LWP::UserAgent::DNS::Hosts;
131              
132             # add entry
133             LWP::UserAgent::DNS::Hosts->register_host(
134             'www.cpan.org' => '127.0.0.1',
135             );
136              
137             # add entries
138             LWP::UserAgent::DNS::Hosts->register_hosts(
139             'search.cpan.org' => '192.168.0.100',
140             'pause.perl.org' => '192.168.0.101',
141             );
142              
143             # read hosts file
144             LWP::UserAgent::DNS::Hosts->read_hosts('/path/to/my/hosts');
145              
146             LWP::UserAgent::DNS::Hosts->enable_override;
147              
148             # override request hosts with peer addr defined above
149             my $ua = LWP::UserAgent->new;
150             my $res = $ua->get("http://www.cpan.org/");
151             print $res->content; # is same as "http://127.0.0.1/" content
152              
153             =head1 DESCRIPTION
154              
155             LWP::UserAgent::DNS::Hosts is a module to override HTTP/HTTPS request
156             peer addresses that uses LWP::UserAgent.
157              
158             This module concept was got from L.
159              
160             =head1 METHODS
161              
162             =over 4
163              
164             =item register_host($host, $peer_addr)
165              
166             LWP::UserAgent::DNS::Hosts->register_host($host, $peer_addr);
167              
168             Registers a pair of hostname and peer ip address.
169              
170             # /etc/hosts
171             127.0.0.1 example.com
172              
173             equals to:
174              
175             LWP::UserAgent::DNS::Hosts->register_hosts('example.com', '127.0.0.1');
176              
177             =item register_hosts(%host_addr_pairs)
178              
179             LWP::UserAgent::DNS::Hosts->register_hosts(
180             'example.com' => '192.168.0.1',
181             'example.org' => '192.168.0.2',
182             ...
183             );
184              
185             Registers pairs of hostname and peer ip address.
186              
187             =item read_hosts($file_or_string)
188              
189             LWP::UserAgent::DNS::Hosts->read_hosts('hosts.my');
190              
191             LWP::UserAgent::DNS::Hosts->read_hosts(<<'__HOST__');
192             127.0.0.1 example.com
193             192.168.0.1 example.net example.org
194             __HOST__
195              
196             Registers "/etc/hosts" syntax entries.
197              
198             =item clear_hosts
199              
200             Clears registered pairs.
201              
202             =item enable_override
203              
204             LWP::UserAgent::DNS::Hosts->enable_override;
205             my $guard = LWP::UserAgent::DNS::Hosts->enable_override;
206              
207             Enables to override hook.
208              
209             If called in a non-void context, returns a L object that
210             automatically resets the override when it goes out of context.
211              
212             =item disable_override
213              
214             LWP::UserAgent::DNS::Hosts->disable_override;
215              
216             Disables to override hook.
217              
218             If you use the guard interface described above,
219             it will be automatically called for you.
220              
221             =back
222              
223             =head1 AUTHOR
224              
225             NAKAGAWA Masaki Emasaki@cpan.orgE
226              
227             =head1 LICENSE
228              
229             This library is free software; you can redistribute it and/or modify
230             it under the same terms as Perl itself.
231              
232             =head1 SEE ALSO
233              
234             L, L, L
235              
236             =cut