簡體   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