2009-01-16 16 views
12

Esta pregunta está relacionada de alguna manera con What’s the simplest way to make a HTTP GET request in Perl?.¿Cómo codifico cadenas de consulta HTTP GET en Perl?

Antes de realizar la solicitud a través de LWP::Simple Tengo un hash de componentes de cadena de consulta que necesito serializar/escapar. ¿Cuál es la mejor manera de codificar la cadena de consulta? Debe tener en cuenta los espacios y todos los caracteres que deben escaparse en URI válidos. Me imagino que probablemente esté en un paquete existente, pero No estoy seguro de cómo encontrarlo.

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

Respuesta

18

URI::Escape hace lo que quiere.

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

En breve: sub escape_hash {my% h = @_; return join '&', map {join '=', map uri_escape ($ _), $ _, $ h {$ _}} teclas% h} –

+0

Pensé en hacer eso también, pero los mapas de anidamiento simplemente no se veían derecho para mí –

+0

Trazar un mapa dentro de (cada uno) con push suena igual de complicado para mí, pero introduce variables temporales innecesarias. –

4

Uso LWP :: agente de usuario en su lugar:

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; 

Se encarga de la codificación para usted.

Si desea una solución de codificación más genérica, consulte HTML::Entities.

EDITAR: URI::Escape es una mejor opción.

+2

¿Por qué es URI: Escape una mejor opción? – cdleary

+0

Puedo estar equivocado, pero HTML \ Entidades no codifica cosas como < to > mientras que URI :: Escape escapa cosas para el URI, como un espacio a% 20. Codifican diferentes cosas, una para HTML y la otra para URI. – gpojd

+5

A menos que me esté perdiendo algo. Esto NO agrega una cadena de consulta al URI de solicitud, sino que agrega los argumentos como encabezados HTTP, que es completamente diferente. http://search.cpan.org/~gaas/libwww-perl-5.834/lib/LWP/UserAgent.pm#REQUEST_METHODS – cliveholloway

25

URI::Escape es probablemente la respuesta más directa, como otros han dado, pero yo recomendaría usar un objeto URI para todo el asunto. URI escapa automáticamente de los parámetros GET (usando 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 

Como un beneficio adicional, LWP::Simple'sobtener función se llevará a un objeto URI ya que es el argumento en lugar de una cadena.

+0

Creo que esta es la mejor solución. – singingfish

+3

tenga en cuenta que esto requerirá: "use URI;" –

4

URI es mucho más simple que URI::Escape para esto. El método query_form() acepta un hash o una 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

utilizar el módulo URI para construir la URL con los parámetros de consulta:

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

encontré esta solución here.

+0

Aunque las soluciones que usan map y URI :: Escape son elegantes ... esto parece más simple y, por lo tanto, lo mejor para mí. – bbarker

Cuestiones relacionadas