我需要一個Perl CGI腳本來獲取一個URL,然後將獲取的結果 - 狀態,標題和內容 - 未改變地返回給CGI環境,以便Web服務器將「代理」URL返回給用戶的瀏覽器就好像他們直接訪問了URL一樣。使用Perl HTTP :: Response和LWP代理HTTP請求的更好方法?
我正在Ubuntu 14.04主機上的Apache Web服務器上運行cgi-bin的腳本,但這個問題應該獨立於服務器平臺 - 任何可以運行Perl CGI腳本的應該都可以。
我試過使用LWP :: UserAgent :: request(),我已經非常接近。它返回一個HTTP :: Response對象,其中包含狀態碼,標題和內容,甚至還有一個「as_string」方法,可將其轉換爲可讀的形式。從CGI角度來看,問題是「as string」將狀態代碼轉換爲「HTTP/1.1 200 OK」而不是「Status:200 OK」,所以Apache服務器不會將輸出識別爲有效的CGI響應。
我可以通過使用HTTP :: Response中的其他方法解決這個問題來拆分各個部分,但似乎沒有公開的方法來獲取封裝的HTTP :: Headers對象以調用其as_string方法;相反,我不得不侵入Perl祝福的對象散列並直接跳出私有「_headers」成員。對我來說這似乎有點邪惡,那麼還有更好的辦法嗎?
下面是一些代碼來說明上述情況。如果你把它放在你的cgi-bin目錄,那麼你可以把它作爲
http://localhost/cgi-bin/lwp-test?url=http://localhost/&http-response=1&show=1
您可以使用不同的URL進行測試,如果你想。如果你設置了http-response=0
(或者完全刪除參數),那麼你就可以得到工作逐件解決方案。如果您設置show=0
(或放棄它),那麼腳本會返回代理請求。如果你有HTTP響應= 0,將與500內部服務器錯誤嗆Apache會返回代理的網頁,如果是1
#!/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環境,並且與我的實際應用程序沒有相似之處。
你能編輯並使實際questin更明顯嗎?我覺得它太隱藏在文本中。什麼是問題? – simbabque
我編輯了這個問題。這是否使它更清晰?基本上它分爲四部分:(1)這是我正在嘗試做的事(代理一個URL獲取); (2)以下是我如何做到的(使用LWP); (3)這裏是我的解決方案的問題(依賴於HTTP :: Response內部結構的知識); (4)有沒有更好的方法? – kbro
在另一種想法上,我發現了[這個答案](http://stackoverflow.com/a/273756/1331451)關於如何創建一個代理。它使我[檢查HTTP :: Daemon](https://metacpan.org/source/GAAS/HTTP-Daemon-6.01/lib/HTTP/Daemon.pm#L440),它有一個send_response方法,它需要一個HTTP :: Response對象。在那裏可能有一些轉換可以滿足你的需求。值得閱讀我認爲的代碼。 – simbabque