File: Utils.pm

package info (click to toggle)
libhttp-proxy-perl 0.304-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, sid, trixie
  • size: 720 kB
  • sloc: perl: 2,576; makefile: 4
file content (132 lines) | stat: -rw-r--r-- 3,422 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package t::Utils;

use strict;
use Exporter ();
use IO::Socket::IP;
use URI ();
use vars qw( @ISA @EXPORT @EXPORT_OK );

@ISA       = qw( Exporter );
@EXPORT    = qw( &server_start &server_next &fork_proxy &web_ok &bare_request );
@EXPORT_OK = @EXPORT;

use HTTP::Daemon;
use LWP::UserAgent;

# start a simple server
sub server_start {

    # create a HTTP::Daemon (on an available port)
    my $daemon = HTTP::Daemon->new(
        LocalHost => 'localhost',
        ReuseAddr => 1,
      )
      or die "Unable to start web server";
    return $daemon;
}

# This must NOT be called in an OO fashion but this way:
# server_next( $server, $coderef, ... );
#
# The optional coderef takes a HTTP::Request as its first argument
# and returns a HTTP::Response. The rest of server_next() arguments
# are passed to &$anwser;

sub server_next {
    my $daemon = shift;
    my $answer = shift;

    # get connection data
    my $conn = $daemon->accept;
    my $req  = $conn->get_request;

    # compute some answer
    my $rep;
    if ( ref $answer eq 'CODE' ) {
        $rep = $answer->( $req, @_ );
    }
    else {
        $rep = HTTP::Response->new(
            200, 'OK',
            HTTP::Headers->new( 'Content-Type' => 'text/plain' ),
            sprintf( "You asked for <a href='%s'>%s</a>", ( $req->uri ) x 2 )
        );
    }

    $conn->send_response($rep);
    $conn->close;
}

# run a stand-alone proxy
# the proxy accepts an optional coderef to run after serving all requests
sub fork_proxy {
    my $proxy = shift;
    my $sub   = shift;

    my $pid = fork;
    die "Unable to fork proxy" if not defined $pid;

    if ( $pid == 0 ) {
        $0 .= " (proxy)";

        # this is the http proxy
        $proxy->start;
        $sub->() if ( defined $sub and ref $sub eq 'CODE' );
        exit 0;
    }

    # back to the parent
    return $pid;
}

# check that the web connection is working
sub web_ok {
    return 0 if $ENV{NO_NETWORK};
    my $ua = LWP::UserAgent->new( env_proxy => 1, timeout => 30 );
    my $res =
      $ua->request(
        HTTP::Request->new( GET => shift||'http://www.google.com/intl/en/' ) );
    return $res->is_success;
}

# send a simple request without LWP::UA
# bare_request($url, $headers, $proxy)
sub bare_request {
    my ($url, $headers, $proxy) = @_;

    # connect directly to the proxy
    my $sock = IO::Socket::IP->new(
        PeerAddr => URI->new($proxy->url)->host,
        PeerPort => URI->new($proxy->url)->port,
        Proto    => 'tcp'
      ) or do { warn "Can't connect to the proxy"; return ""; };
    
    # send the request
    print $sock "GET $url HTTP/1.0\015\012",
                $headers->as_string( "\015\012" ), "\015\012";
    my $content = join "", <$sock>;

    # close the connection to the proxy
    close $sock or warn "close: $!";
    return $content;
}

package HTTP::Proxy;

# return the requested internal filter stack
# _filter_stack( body|header, request|response, HTTP::Message )
sub _filter_stack {
    my ( $self, $part, $mesg ) = splice( @_, 0, 3 );
    die "No <$part><$mesg> filter stack"
      unless $part =~ /^(?:header|body)$/
      and $mesg =~ /^(?:request|response)$/;

    for (@_) {
        die "$_ is not a HTTP::Request or HTTP::Response"
          unless ( ref $_ ) =~ /^HTTP::(Request|Response)$/;
        $self->{ lc $1 } = $_;
    }
    $self->{response}->request( $self->{request} );
    return $self->{$part}{$mesg};
}