7

geonames.org サーバーから何かを取得するために使用wgetすると、2 つの IP アドレスが報告され、最初のアドレスは失敗しますが、2 番目のアドレスから取得されます。

Resolving ws.geonames.org (ws.geonames.org)... 5.9.41.208, 176.9.107.169
Connecting to ws.geonames.org (ws.geonames.org)|5.9.41.208|:80... failed: Connection refused.
Connecting to ws.geonames.org (ws.geonames.org)|176.9.107.169|:80... connected.
HTTP request sent, awaiting response... 200 OK

しかし残念ながら、LWP::UserAgent と HTTP::Request を使用して perl 経由でアクセスする必要があります。最初の IP が失敗した場合、2 番目の IP を試すにはどうすればよいですか?

    my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(
    GET =>
      "http://ws.geonames.org/countrySubdivision?lat=$lat&lng=$long&radius=$radius&username=xyzzy");

my $res = $ua->request($req);
4

2 に答える 2

6

自分で行うことができます。 を使用してすべての IP アドレスNet::DNS::Resolverを取得し、正常な応答が得られるまですべての IP アドレスを試します。サーバーが名前ベースの仮想ホストを実行している場合、IP アドレスを使用する場合は、"Host" ヘッダーを自分で指定する必要があることに注意してください。

次の行のようなものが機能します。このためのCPANモジュールさえあるかもしれませんが、私はチェックしませんでした:

use Net::DNS;
use LWP::UserAgent;

my @addrs;
{
    my $res   = Net::DNS::Resolver->new;
    my $query = $res->search("ws.geonames.org");
    if ($query) {
        for my $rr ($query->answer) {
            if ($rr->type eq "A") {
                push @addrs, $rr->address;
            }
        }
    } else {
        die "DNS query failed: ", $res->errorstring, "\n";
    }
}

my $ua = LWP::UserAgent->new;

my $res;
for my $addr (@addrs) {
    $res = $ua->get("http://$addr/countrySubdivision?lat=$lat&lng=$long&radius=$radius&username=xyzzy", Host => 'ws.geonames.org');
    last if $res->is_success;
}
于 2013-08-24T23:27:35.360 に答える
1

IPアドレスに直接アクセスできない場合を除いて、Slavenのソリューションは問題ありません。その場合、次のように動作します。

local @LWP::Protocol::http::EXTRA_SOCK_OPTS = (
                                           PeerAddr   => 'my_hostname',
                                           MultiHomed => 1,
                                          );
my $response = $ua->post('https://my_hostname/...', ...);
于 2015-04-21T15:00:38.633 に答える