繁体   English   中英

使用Perl HTTP :: Response和LWP代理HTTP请求的更好方法?

[英]Better way to proxy an HTTP request using Perl HTTP::Response and LWP?

我需要一个Perl CGI脚本,该脚本将获取URL,然后将获取的结果(状态,标头和内容)保持不变,而不会更改到CGI环境,以便Web服务器将“代理” URL返回给用户的浏览器,就像他们直接访问了网址。

我正在Ubuntu 14.04主机上的Apache Web服务器中的cgi-bin中运行脚本,但是此问题应独立于服务器平台-可以运行Perl CGI脚本的任何东西都应该能够做到。

我已经尝试过使用LWP :: UserAgent :: request(),并且已经很接近了。 它返回一个HTTP :: Response对象,该对象包含状态码,标头和内容,甚至还具有一个“ as_string”方法,该方法会将其转换为易于理解的形式。 从CGI角度来看,问题是“作为字符串”将状态代码转换为“ HTTP / 1.1 200 OK”,而不是“ Status:200 OK”,因此Apache服务器无法将输出识别为有效的CGI响应。

我可以通过使用HTTP :: Response中的其他方法来拆分各个部分来解决此问题,但是似乎没有公开的方法来获取封装的HTTP :: Headers对象以调用其as_string方法; 取而代之的是,我不得不侵入Perl祝福的对象哈希,并直接提取私有的“ _headers”成员。 对我来说,这似乎有点邪恶,所以有更好的方法吗?

这里是一些说明上述内容的代码。 如果将其放在cgi-bin目录中,则可以将其称为

HTTP://本地主机/的cgi-bin / LWP测试URL = HTTP://本地主机/&HTTP的响应= 1&显示= 1

如果需要,可以使用其他URL进行测试。 如果将http-response=0 (或完全删除该参数),则将得到工作中的逐个解决方案。 如果设置show=0 (或删除它),则脚本将返回代理请求。 如果您具有http-response = 0,则Apache将返回代理页面,如果为1,则将显示500 Internal Server Error。

#!/usr/bin/perl

use strict;
use warnings;

use CGI::Simple;
use HTTP::Request;
use HTTP::Response;
use LWP::UserAgent;

my $q = CGI::Simple->new();
my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new(GET => $q->param('url'));
my $res = $ua->request($req);

# print a text/plain header if called with "show=1" in the query string
# so proxied URL response is shown in browser, otherwise just output
# the proxied response as if it was ours.
if ($q->param('show')) {
    print $q->header("text/plain");
    print "\n";
}

if ($q->param('http-response')) {
    # This prints the status as "HTTP/1.1 200 OK", not "Status: 200 OK".
    print $res->as_string;
} else {
    # This works correctly as a proxy, but using {_headers} to get at
    # the private encapsulated HTTP:Response object seems a bit evil.
    # There must be a better way!
    print "Status: ", $res->status_line, "\n";
    print $res->{_headers}->as_string;
    print "\n";
    print $res->content;
}

请记住,该脚本的编写纯粹是为了演示如何将HTTP::Response对象转发到CGI环境,与我的实际应用程序没有任何相似之处。

您可以使用$res->headers方法在$res->headers $res->{_headers}$res->{_headers}响应对象的内部,该方法返回实际使用的HTTP :: Headers实例。 HTTP :: Response继承自HTTP :: Message

然后看起来像这样:

print "Status: ", $res->status_line, "\n";
print $res->headers->as_string;

尽管看起来还不是很漂亮,但看起来似乎不太邪恶。

正如simbabque所指出的那样,HTTP :: Response通过从HTTP :: Message继承而具有headers方法。 我们可以使用HTTP::Response->header将状态代码推送到嵌入式HTTP :: Headers对象中,从而整理状态代码的处理,然后使用headers_as_string更清晰地打印出标题。 这是最终的脚本:

#!/usr/bin/perl

use strict;
use warnings;

use CGI::Simple;
use HTTP::Request;
use HTTP::Response;
use LWP::UserAgent;

my $q = CGI::Simple->new();
my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new(GET => $q->param('url'));
my $res = $ua->request($req);

# print a text/plain header if called with "show=1" in the query string
# so proxied URL response is shown in browser, otherwise just output
# the proxied response as if it was ours.
if ($q->param('show')) {
    print $q->header("text/plain");
}

# $res->as_string returns the status in a "HTTP/1.1 200 OK" line rather than
# a "Status: 200 OK" header field so it can't be used for a CGI response.
# We therefore have a little more work to do...

# convert status from line to header field
$res->header("Status", $res->status_line);
# now print headers and content - don't forget a blank line between the two
print $res->headers_as_string, "\n", $res->content;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM