Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

binding to a vhost using LWP

by strfry() (Monk)
on Apr 07, 2003 at 14:16 UTC ( [id://248608]=perlquestion: print w/replies, xml ) Need Help??

strfry() has asked for the wisdom of the Perl Monks concerning the following question:

i'm curious as to whether anyone knows of a way to bind my socket to an arbitrary address using HTTP::Request / LWP::UserAgent, or even better, LWP::Simple. the script i'm writing will be pulling files off of other websites, and as such i'd really like to avoid using anything Socket or IO::Socket related if at all possible; i can see no point in trail blazing when there's a well-paved and well-proven highway available. (:

in Socket terms, i'd like to do something like this:
bind(SOCK, sockaddr_in( $port, inet_aton( $vhost ) ) );
thanks all!

strfry(reality)

Replies are listed 'Best First'.
Re: binding to a vhost using LWP
by Thelonius (Priest) on Apr 07, 2003 at 15:26 UTC
    It looks like LWP::Protocol::http.pm will let you use a variable called @EXTRA_SOCK_OPTS to do what you want. I think the code would be:
    use LWP::Protocol::http; @LWP::Protocol::http::EXTRA_SOCK_OPTS = (LocalAddr => "$vhost:$port");
    then do the normal LWP stuff. Not tested in any way.
Re: binding to a vhost using LWP
by IlyaM (Parson) on Apr 07, 2003 at 14:59 UTC
    If you want to force LWP to connect via some specific IP/port you can set this IP/port as an address of proxy. For example:
    use LWP::UserAgent; use HTTP::Request::Common; my $ua = LWP::UserAgent->new; $ua->proxy(http => 'http://1.2.3.4:5678/'); my $response = $ua->request(GET 'http://my.domain/path');

    --
    Ilya Martynov, ilya@iponweb.net
    CTO IPonWEB (UK) Ltd
    Quality Perl Programming and Unix Support UK managed @ offshore prices - http://www.iponweb.net
    Personal website - http://martynov.org

Re: binding to a vhost using LWP
by pg (Canon) on Apr 07, 2003 at 21:12 UTC
    This is doable. For LWP::UserAgent, the actual socket is in HTTP::Protocol and its subclasses. Those classes accept extra socket configuration from global @EXTRA_SOCK_OPTS. That’s where you can set LocalAddr and LocalPort.

    Just do something like this: (code is tested.)
    #!/usr/bin/perl use LWP::UserAgent; use strict; push(@LWP::Protocol::http::EXTRA_SOCK_OPTS, "LocalPort" => "7000"); my $a = new LWP::UserAgent(); $a->proxy('http', 'http://ofgfw1.owfg.com:8080/'); $a->get("http://www.yahoo.com/");
    When I was testing, I added extra code in LWP::Protocol::http.pm after the socket is created, to make sure the local binding is correct:
    print $sock->sockaddr(), "\n"; print $sock->sockport(), "\n";
    And this passed.
Re: binding to a vhost using LWP
by dws (Chancellor) on Apr 07, 2003 at 17:05 UTC
    The title of this question raised a flag. The "v" in "vhost" typically means "virtual", which means something very specific when you're talking about hosting web sites (or targeting sites that have been virtually hosted). In virtual hosting, a number of different domains share a single IP address, with a single web server handling all requests (unless there's fancy load balancing going on, but let's imagine there's not). To distinguish incoming HTTP requests, the server examines the request envelope, looking for an HTTP/1.1 "Host" header, which carries the name of the target virtual host. The argument of the Host header is then used to "dispatch" to the desired virtual site.

    All common web browsers are HTTP/1.1 compliant, and will issue a Host header as part of a request.

    LWP is HTTP/1.1 compliant, and will automatically add a Host header to outgoing requests. But for this to work, you need to supply LWP with the target domain name, not the target's IP address.

    None of this requires that you dive under the covers and invoke bind() yourself. Look over the LWP POD documentation for examples.

Re: binding to a vhost using LWP
by zby (Vicar) on Apr 07, 2003 at 14:30 UTC
    For the task of pulling files off websites you don't need to fiddle with Socket calls the library - LWP::UserAgent does that for you. I am not sure what exactly you want to do. Why do you need to use low level Socket calls when you use LWP::UserAgent?
    Update: Perhaps you have problem with the address - you have it as a number - while the UserAgent needs the dotted string?
      well, perhaps i've missed something, but i've as of yet been able to find any way to manipulate the underlying socket using LWP::UserAgent. in a nutshell, the machine i'm developing on is has several IP's that go to several lan/wan networks, and perhaps two or three that actually go out to the real world; i want to bind to an arbitrary IP address depending on the situation.

      a really good example of why this is necessary, would be pulling XML/RDF files from computers that are inside of a LAN that is not accessable from the internet, other than from the outside webserver. or perhaps you have two IP's on a machine, from two totally different IP blocks, and only one of the IP's can access the files due to firewalling. or whatever. (:

      i'm trying that use base now, i'll update whenever i get a chance. thanks again. (:

      strfry(reality)
Re: binding to a vhost using LWP
by perrin (Chancellor) on Apr 07, 2003 at 15:09 UTC
    If the resource you are contacting is an HTTP server of some kind, then just use LWP normally, specifying host and port. If it not an HTTP server, you should stay away from LWP and use something else like IO::Socket.

    UPDATE: Can you explain why this is not as simple as specifying an IP to LWP?

      Can you explain why this is not as simple as specifying an IP to LWP?
      What he wants to do is specify the IP address (and perhaps port) that he is coming from. A computer may have more than one IP address--most commonly because it has more than one network interface card.
        Thanks, this question makes much more sense to me now.
Re: binding to a vhost using LWP
by nothingmuch (Priest) on Apr 07, 2003 at 14:23 UTC
    As i doubt you could get access to the socket, especially during construction, i'd make a use base relationship with the desired modules, and modify the constructor to create your own type of socket.
    I must admit i only skimmed the docs before writing this, and haven't made completely sure, but i'm in doubt that i'm wrong. It's something too specific for a general module. If you do that you can avoid most of the work, because the interface remains essentially the same.

    Update: To explicitly decide what interface to bind the outgoing socket to that must be done before connect. My mistake was that i assumed connect happens at construction. You simply need to redefine the method that starts the connection...

    -nuffin
    zz zZ Z Z #!perl

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://248608]
Approved by nothingmuch
Front-paged by diotalevi
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (6)
As of 2024-04-25 15:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found