![](/img/trans.png)
[英]HTTP::Request in perl using LWP:UserAgent for authentification: CRFS issue
[英]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.