【问题标题】:How may I bypass LWP's URL encoding for a GET request?如何绕过 LWP 的 GET 请求 URL 编码?
【发布时间】:2014-03-25 11:44:18
【问题描述】:

我正在与似乎已损坏的 HTTP 守护程序交谈,我需要发出一个 GET 请求,该请求在 URL 中包含一个管道 | 字符。

LWP::UserAgent 在发送请求之前转义管道字符。

例如,传入的 URL 为:

https://hostname/url/doSomethingScript?ss=1234&activities=Lec1|01

被传递给 HTTP 守护进程

https://hostname/url/doSomethingScript?ss=1234&activities=Lec1%7C01

这是正确的,但不适用于这个损坏的服务器。

如何覆盖或绕过 LWP 及其朋友正在执行的编码?

注意

我在 StackOverflow 上看到并尝试了其他解决类似问题的答案。这里的区别似乎是这些答案正在处理POST 请求,其中URL 的formfield 部分可以作为键/值对数组或'Content' => $content 参数传递。这些方法不适用于我的 LWP 请求。

我还尝试构建一个HTTP::Request 对象并将其传递给LWP,并将完整的URL 直接传递给LWP->get()。两种方法都没有骰子。


应 Borodin 的要求,这是我正在使用的代码的净化版本

#!/usr/local/bin/perl -w
use HTTP::Cookies;
use LWP;

my $debug = 1;

# make a 'browser' object
my $browser = LWP::UserAgent->new();

# cookie handling...
$browser->cookie_jar(HTTP::Cookies->new(
             'file' => '.cookie_jar.txt',
             'autosave' => 1,
             'ignore_discard' => 1,
             ));

# proxy, so we can watch...
if ($debug == 1) {
    $browser->proxy(['http', 'ftp', 'https'], 'http://localhost:8080/');
}

# user agent string (pretend to be Firefox)
$agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.7.12) Gecko/20050919 Firefox/1.0.7';

# set the user agent
$browser->agent($agent);

# do some things here to log in to the web site, accept session cookies, etc. 
# These are basic POSTs of filled forms. Works fine.
# [...]

my $baseURL = 'https://hostname/url/doSomethingScript?ss=1234&activities=VALUEA|VALUEB';

@values = ['Lec1', '01', 'Lec1', '02'];

while (1) {
    if (scalar(@values) < 2) { last; }

    my $vala = shift(@values);
    my $valb = shift(@values);

    my $url = $basEURL;
    $url =~ s/VALUEA/$vala/g;
    $url =~ s/VALUEB/$valb/g;

    # simplified. Would usually check request for '200' response, etc...
    $content = $browser->get($url)->content();

    # do something here with the content

    # [...]

    # fails because the '|' character in the url is escaped after it's handed 
    # to LWP

}

# end

【问题讨论】:

  • 作为一个兴趣点,我发现了 LWP::Curl 模块及其 auto_encode() 方法。我已经能够证明,如果这样创建一个对象:$lwpcurl = LWP::Curl-&gt;new();并设置$lwpcurl-&gt;auto_encode(0);,带有我在问题中描述的形式的 URL 的后续请求将传递给 HTTP 守护程序,而无需进一步处理。对我来说,使用 LWP::UserAgent 仍然比 LWP::Curl 更可取(我必须重新编写很多代码),所以我会让我的问题继续存在,希望有人能够帮助。
  • LWP 库设计得非常好,几乎每个点都有钩子。请出示您的代码。你在打一个简单的$ua-&gt;get 电话吗?您是否尝试过构建 HTTP::Request 对象并在其上调用 $ua-&gt;request
  • 由 HTTP::Request 使用的 URI 类完成
  • 作为 stackoverflow 新手,我无法回答自己的问题。所以,一个评论:我已经找到了一种方法来完成这项工作,在 Joe Schaefer 的帖子 (#13) 中的 perlmonks 线程 computer-programming-forum.com/53-perl/11cfc4991e0b3d0a.htm 中。本质上,创建一个HTTP::Request 对象,传入“损坏的”url:my $url = 'hostname/url/…';我的 $request = HTTP:Request->new(GET => $url); HTTP::Request 修改 URL: print $request->as_string;证明了这一点。 ...
  • 付出了这么多努力为未来的读者留下了一个解释,你很可能仅仅通过这个问题就产生了足够的代表。欢迎来到 SO。

标签: perl url encoding uri lwp


【解决方案1】:

正如@bchgys 在他的评论中提到的,这(几乎)在linked thread 中得到了回答。这里有两种解决方案:

第一个也可以说是最干净的方法是在本地覆盖 URI::Escape 中的转义映射以不修改管道字符:

use URI;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new();
my $res;
{
    # Violate RFC 2396 by forcing broken query string
    # local makes the override take effect only in the current code block
    local $URI::Escape::escapes{'|'} = '|';
    $res = $ua->get('http://server/script?q=a|b');
}
print $res->request->as_string, "\n";

或者,您可以在创建请求后直接在请求中修改 URI 来简单地撤消转义:

use HTTP::Request;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new(GET => 'http://server/script?q=a|b');

# Violate RFC 2396 by forcing broken query string
${$req->uri} =~ s/%7C/|/; 

my $res = $ua->request($req);
print $res->request->as_string, "\n";

第一个解决方案几乎肯定更可取,因为它至少依赖于导出和记录的 %URI::Escape::escapes 包变量,因此这可能与您使用受支持的 API 执行此操作一样接近。

请注意,在任何一种情况下,您都违反了 RFC 2396,但如前所述,在与您无法控制的损坏服务器通信时,您可能别无选择。

【讨论】:

  • 谢谢@lasse,您为逃生地图添加了难以捉摸的本地覆盖。我知道可以这样做,但不确定具体如何,所以谢谢。您回答的第二部分与我在 cmets 中提供的答案大致相同,但我认为您的回答更有说服力,所以我将其作为答案!我特别喜欢有点刻薄的“违反 RFC2396”部分! :-)
  • 关于“难以捉摸”的地方的好点。我添加了一条评论,以阐明很多人没有意识到的目的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
  • 2022-07-28
  • 1970-01-01
  • 2013-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多