2009-01-16 64 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