2009-01-16 7 views
12

Diese Frage steht in etwa im Zusammenhang mit What’s the simplest way to make a HTTP GET request in Perl?.Wie codiere ich HTTP-GET-Abfragezeichenfolgen in Perl?

Bevor ich die Anfrage über LWP::Simple mache, habe ich einen Hash der Query-String-Komponenten, die ich serialisieren/entkommen muss. Wie kann die Abfragezeichenfolge am besten codiert werden? Es sollte Leerzeichen und alle Zeichen berücksichtigen, die in gültigen URIs maskiert werden müssen. Ich denke, es ist wahrscheinlich in einem bestehenden Paket, aber Ich bin mir nicht sicher, wie ich es finden soll.

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); 

Antwort

18

URI::Escape tut, was Sie wollen.

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

Kurz gesagt: sub escape_hash {my% h = @_; Return join '&', Karte {join '=', Karte uri_escape ($ _), $ _, $ h {$ _}} Tasten% h} –

+0

Ich tue das auch, aber die Schachtelung von Karten sah einfach nicht aus direkt zu mir. –

+0

Map-Innenseite für (jeden) mit Push klingt für mich kompliziert, aber es führt unnötige temporäre Variable. –

4

Verwenden LWP :: Useragent statt:

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; 

Es kümmert sich um die Codierung für Sie.

Wenn Sie eine allgemeinere Codierungslösung wünschen, finden Sie unter HTML::Entities.

EDIT: URI::Escape ist eine bessere Wahl.

+2

Warum ist URI: Flucht eine bessere Wahl? – cdleary

+0

Ich kann falsch sein, aber nicht HTML :: Entities codieren Dinge wie < to > während URI :: Escape entkommt Dinge für den URI, wie ein Leerzeichen zu% 20. Sie kodieren verschiedene Dinge, eines für HTML und das andere für URIs. – gpojd

+5

Es sei denn, ich vermisse etwas. Dies fügt dem Anforderungs-URI KEINE Abfragezeichenfolge hinzu, sondern fügt die Argumente als HTTP-Header hinzu, was völlig anders ist. http://search.cpan.org/~gaas/libwww-perl-5.834/lib/LWP/UserAgent.pm#REQUEST_METHODS – cliveholloway

25

URI::Escape ist wahrscheinlich die direkteste Antwort, wie andere gegeben haben, aber ich würde empfehlen, ein URI Objekt für die gesamte Sache zu verwenden. URI entkoppelt automatisch die GET-Parameter für Sie (mit 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 

Als zusätzlichen Bonus, LWP::Simple'serhalten Funktion ein URI Objekt nehmen wird, wie es Argument ist anstelle einer Zeichenfolge.

+0

Ich denke, das ist die beste Lösung. – singingfish

+3

beachten Sie folgendes: "URI verwenden"; –

4

URI ist viel einfacher als URI::Escape dafür. Das Verfahren query_form() einen Hash oder eine hashref nimmt:

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

Verwenden Sie das Modul URI die URL mit den Abfrageparametern aufzubauen:

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"); 

I here diese Lösung gefunden.

+0

Obwohl Lösungen mit Map und URI :: Escape elegant sind ... das scheint mir am einfachsten und somit am besten zu sein. – bbarker