HTTP-Proxy-Selective

 view release on metacpan or  search on metacpan

script/selective_proxy  view on Meta::CPAN

        # 502 Bad Gateway / 504 Gateway Timeout
        # Note to implementors: some deployed proxies are known to
        # return 400 or 500 when DNS lookups time out.
        my $response = HTTP::Response->new( 200 );
        $response->content_type( "text/plain" );
        $self->response($response);
        return $last;
    }

    # send the response headers (FIXME more headers required?)
    my $response = HTTP::Response->new(200);
    $self->response($response);
    $self->{$_}{response}->select_filters( $response ) for qw( headers body );

    $self->_send_response_headers( $served );

    # we now have a TCP connection to the upstream host
    $last = 1;
    my $class = ref($conn);
    { no strict 'refs'; unshift(@{$class . "::ISA"}, 'IO::Socket::SSL'); } # Forcibly change classes the socket inherits from
    $class->start_SSL($conn, 
        SSL_server => 1, 
        SSL_key_file => $key,
        SSL_cert_file => $cert, # Turn our client socket into SSL.
    ) or warn("Could not start SSL");
    ${*$conn}{'httpd_nomore'} = 0; # Pay no attention to the Connection: close header behind the curtain.
    {   # Build a method to fiddle with the request object we get from the client, as it needs to http->https
        my $old_setrequest_method = \&HTTP::Proxy::request;
        my $new_request_method = sub {
            my ($self, $new_req) = @_;
            if ($new_req) {
                use Data::Dumper;
                if (!$new_req->uri->scheme or $new_req->uri->scheme eq 'http') {
                    $new_req->uri->scheme('https');
                    $new_req->uri->host($new_req->header('Host'));
                }
            }
            $old_setrequest_method->($self, $new_req);
        };
        # And monkeypatch it into HTTP proxy, using local to restrict it by lexical scope
        # so that it goes away once we exit the block (i.e. the CONNECT method finishes).
        no warnings qw[once redefine];
        local *HTTP::Proxy::request = $new_request_method;
        use warnings qw[once redefine];
        $self->serve_connections($conn);
    }
    $conn->stop_SSL($conn);
    return $last;
}
{
    no warnings qw(once redefine);
    *HTTP::Proxy::_handle_CONNECT = \&_handle_CONNECT;
}

our %http_proxy_defaults = (
    port                    => 3128,
    max_clients             => 10,
    max_requests_per_child  => 100,
    min_spare_servers       => 1,
    max_spare_servers       => 5,
    keep_alive              => 0,
    max_keep_alive_requests => 1,
    keep_alive_timeout      => 60,
    engine                  => 'NoFork',
);

sub _generate_proxy_config {
    my %in_params = @_;
    my %params;
    foreach my $k (keys %http_proxy_defaults) {
        $params{$k} = exists $in_params{$k} ? $in_params{$k} : $http_proxy_defaults{$k};
    }
    return %params;
}

my $_help = q{No config file passed on command line.
    
Please create a file in a text editor which looks like this:
# Note that more options are available, please see example_config.ini in the distribution for usage.
port = 3128
debug = 1
#upstream_proxy = proxy.example.com:8080

[search.cpan.org]
/s/=/tmp/css
/stuff/=/tmp/stuff

[www.google.com]
/js/=/tmp/js
/some/file.jpg=/tmp/somefile.jpg

and save it in your editor. Then re-run selective_proxy, appending the configuration file name.
};

sub main {
    my $conf_file = shift(@ARGV);
    die($_help) unless ($conf_file);
    die("Config file passed on command line ($conf_file) could not be read.\n") unless (-r $conf_file);

    my %config = %{ Config::Tiny->read( $conf_file ) };

    my $root_config = delete $config{_};
    my $debug = delete $root_config->{debug};
    my $upstream_proxy = delete $root_config->{upstream_proxy};

    my $proxy = HTTP::Proxy->new( 
        _generate_proxy_config( %{$root_config} ),
        max_connections => 0, # Not lettng the users stamp on this..
    );
    $proxy->init;
    die("No agent") unless $proxy->{agent};
    warn("Upstream proxy: $upstream_proxy") if $upstream_proxy;
    $proxy->{agent}->proxy([qw/http https/], $upstream_proxy) if $upstream_proxy;;
    
    $proxy->push_filter( 
        method => 'GET, HEAD',
        request => HTTP::Proxy::Selective->new(\%config, $debug)
    );
    warn("Starting proxy at " . $proxy->url . "\n");
    $proxy->start;
}

main() unless caller();



( run in 0.736 second using v1.01-cache-2.11-cpan-71847e10f99 )