2009-01-16 66 views
12

此問題與What’s the simplest way to make a HTTP GET request in Perl?有些相關。如何在Perl中編碼HTTP GET查詢字符串?

通過LWP::Simple發出請求之前,我有一個查詢字符串組件的散列,我需要序列化/轉義。 對查詢字符串進行編碼的最佳方式是什麼?它應該考慮空格和需要在有效URI中轉義的所有字符。我想這可能是在現有的包中,但是我不知道如何去找到它。

use LWP::Simple; 
my $base_uri = 'http://example.com/rest_api/'; 
my %query_hash = (spam => 'eggs', foo => 'bar baz'); 
my $query_string = urlencode(query_hash); # Part in question. 
my $query_uri = "$base_uri?$query_string"; 
# http://example.com/rest_api/?spam=eggs&foo=bar+baz 
$contents = get($query_uri); 

回答

18

URI::Escape做你想做的。

use URI::Escape; 

sub escape_hash { 
    my %hash = @_; 
    my @pairs; 
    for my $key (keys %hash) { 
     push @pairs, join "=", map { uri_escape($_) } $key, $hash{$key}; 
    } 
    return join "&", @pairs; 
} 
+0

不久:sub escape_hash {my%h = @_;返回連接'&',地圖{連接'=',地圖uri_escape($ _),$ _,$ h {$ _}}鍵%h} – 2009-01-16 13:03:16

+0

我也這樣做,但嵌套地圖只是沒有看對我來說。 – 2009-01-16 13:08:48

+0

對於(每個)內部映射,推送聲音對我而言同樣複雜,但它會引入不需要的臨時變量。 – 2009-01-16 21:50:10

4

使用LWP :: UserAgent的,而不是:

use strict; 
use warnings; 

use LWP::UserAgent; 

my %query_hash = (spam => 'eggs', foo => 'bar baz'); 

my $ua = LWP::UserAgent->new(); 
my $resp = $ua->get("http://www.foobar.com", %query_hash); 

print $resp->content; 

它負責編碼的爲您服務。

如果您想要更通用的編碼解決方案,請參閱HTML::Entities。編輯:URI::Escape是一個更好的選擇。

+2

爲什麼URI:逃避一個更好的選擇? – cdleary 2009-01-16 01:56:13

25

URI::Escape可能是最直接的答案,正如其他人所給出的,但我會建議使用整個事物的一個URI對象。 URI自動轉義GET參數(使用URI :: Escape)。

my $uri = URI->new('http://example.com'); 
$uri->query_form(foo => '1 2', bar => 2); 
print $uri; ## http://example.com?foo=1+2&bar=2 

作爲額外的獎勵,LWP::Simple's得到功能將採取URI對象作爲它的參數,而不是一個字符串。

4

URI遠遠比這個URI::Escape簡單。 query_form()接受一個哈希或hashref方法:

use URI; 
my $full_url = URI->new('http://example.com'); 
$full_url->query_form({"id" => 27, "order" => "my key"}); 
print "$full_url\n";  # http://example.com?id=27&order=my+key 
3

使用模塊URI與查詢參數來構建URL:

use LWP::Simple; 
use URI; 

my $uri_object = URI->new('http://example.com/rest_api/'); 
$uri_object->query_form(spam => 'eggs', foo => 'bar baz'); 

$contents = get("$uri_object"); 

我發現這個解決方案here