in reply to Using Virtual interface through WWW::Mechanize

You could try something like this old code I had lying around (translation: this is old and I don't know if it still works with recent versions of LWP). Set $ENV{LWP_LOCAL_ADDR} before you create each instance and it'll use that for the local socket address.

package MyHTTP; use base qw(LWP::Protocol::http); sub _new_socket { my($self, $host, $port, $timeout) = @_; local($^W) = 0; # IO::Socket::INET can be noisy my @args = (PeerAddr => $host, PeerPort => $port, Proto => 'tcp', Timeout => $timeout, ); push @args, LocalAddr => $ENV{LWP_LOCAL_ADDR} if exists $ENV{LWP_LOCAL_ADDR}; my $sock = IO::Socket::INET->new( @args ); unless ($sock) { # IO::Socket::INET leaves additional error messages in $@ $@ =~ s/^.*?: //; die "Can't connect to $host:$port ($@)"; } $sock; } LWP::Protocol::implementor( 'http', 'MyHTTP' ); 1;

You also could alter it from using %ENV to maybe look at a global instead. I'm not aware of a better way of passing options down through from the LWP::UserAgent level (not to mention from Mechanize) to this level though; would be nice if you got a reference to that instance as an arg to _new_socket.

Replies are listed 'Best First'.
Re^2: Using Virtual interface through WWW::Mechanize
by ikegami (Patriarch) on Jul 28, 2006 at 19:47 UTC

    _extra_sock_opts should overriden instead of _new_socket for forward compatibility. For example, your solution breaks connection caching.

    package MyHTTP; use base qw(LWP::Protocol::http); sub _extra_sock_opts { my ($self, $host, $post) = @_ my @opts = $self->SUPER::_extra_sock_opts($host, $post); push @opts, LocalAddr => $ENV{LWP_LOCAL_ADDR} if exists $ENV{LWP_LOCAL_ADDR}; return @opts; } LWP::Protocol::implementor( 'http', 'MyHTTP' ); 1;
    or just
    push @LWP::Protocol::http::EXTRA_SOCK_OPTS, LocalAddr => $ENV{LWP_LOCAL_ADDR} if exists $ENV{LWP_LOCAL_ADDR};