2011-09-09 41 views
1

我正在努力實現如何使用Perl獲取頂級網址的路徑信息?

給出一個頂級網址,如http://www.myapp.com/

如果有人要求:

http://www.myapp.com/questions/id/1

我想要得到的「問題/ ID/1「部分,並將其傳遞給適當的Perl腳本以檢索所需的資源。

我已經取得了

目前,我知道該怎麼做,如果有一個在URL額外的水平,像這樣:

http://www.myapp.com/model/questions/id/1

當「模特」是一個簡單的典型的Perl CGI腳本,除了它沒有「.pl」擴展名,並且Apache perl處理程序被配置爲處理這個,「questions/id/1」部分被解釋爲路徑信息(通過CGI-> path_info())傳遞給「模型」。

我去安德魯Hanenkamp的文章這種想法對onlamp.com主題: Developing RESTful Web Services in Perl

什麼仍然是錯的

這種方法,然而,這並不爲頂級網址工作,因爲有沒有地方放置「模型」或任何處理程序被稱爲。我試圖在配置中設置默認文檔設置,以使http://www.myapp.com/默認爲http://www.myapp.com/modle

讓打字http://www.myapp.com/questions/id/1作爲http://www.myapp.com/model/questions/id/1

處理然而,阿帕奇認爲這是一個404錯誤。

我該如何做到這一點?這甚至是Perl的工作,或者更好地處理Apache配置級別,或者可能攻擊一些Apache API來捕獲404錯誤並從那裏提取「/ questions/id/1」部分?我不知道。也許這裏有人知道。 ;-)

注:道歉問這個問題的措辭長和迂迴的方式。我不太清楚引出主題答案所需的術語是什麼。在這裏和其他地方提出這個問題時,提到一個以R開頭並以T結尾的四字母單詞,這引起了關於所述字母詞的性質的熱烈討論,以及對使用某個框架或其他框架的意義不大但無益的建議。我只是想知道這些框架是如何實現這個功能的,我想在Perl中實現一個來學習如何去做。

更新: 其中一個建議的答案讓我嘗試mod_rewrite。作品。但是,爲每個映射手動設置Apache的conf是不切實際的。進一步的搜索讓我看到O'Reilly的書籍「Practical mod_perl」。其中,Bekman和Cholet寫道通過Apache CPAN包以編程方式訪問mod_rewrite來設置重寫。 Appendix 10 : "mod_rewrite in Perl"現在編寫一些代碼來測試本書的想法。同時,如果有更好的方法來實現這一點,請分享。

結論

原型2 URI路由/調度程序(或Whatchamacallit)腳本後,一個依靠mod_rewrite的調用它,而另一個上的ErrorDocument;我得出結論,mod_rewrite是實現這一點的正確方法。

ErrorDocument方法錯誤,因爲它不保留來自重定向頁面的POST數據。 由於發送POST請求到http://www.myapp.com/questions來創建新資源是不可能的,因爲POST數據對ErrorDocument調用的自定義錯誤處理程序腳本不可用。此外,由於每個定義的請求都不會訪問物理文件,因此Apache的錯誤日誌將充滿spurios 404文件找不到的錯誤。這可能是一個巨大的問題是服務器的交易量很高。感謝大家指點我正確的方向。現在我的好奇心已經飽和了。

+0

如果有人認爲問題措辭不正確,建議更改。我很難理解要使用的正確術語。謝謝。 – GeneQ

+0

你可以給標題添加'CGI' - '使用Perl'有點含糊! – plusplus

+0

你的答案(yko,evil otto)都是很好的有效方法來完成這項工作。 :-)但是,所有事情都是平等的,我傾向於在這一點上進行重寫,因爲我認爲,爲了重新路由而發生錯誤是一種美學上不太吸引人的方法。讓我們讓社羣在決定選擇哪個答案之前對這些不同的方法進行投票。 – GeneQ

回答

1

您可以在.htaccess文件或Apache配置文件中定義重寫規則。 詳情請參閱mod_rewrite

在你的情況.htaccess文件可能看起來像:

AddHandler cgi-script .cgi 
Options +ExecCGI 

RewriteEngine on 

RewriteRule ^(questions/id/.*)$ model.cgi/$1 [L] 

,如果你需要處理的只是/question/id/請求,這應該工作。但是你可能想要通過你的Perl應用程序來處理所有請求。所以實際上將所有請求傳遞給您的應用程序可能是個好主意例如:

RewriteRule ^(.*)$ app.cgi/$1 [L] 

而讓你的應用程序發送請求比。 除......總有一些例外。您需要讓Apache爲您提供靜態文件。而且您需要Apache不要將您的應用程序文件(可執行文件和配置文件)作爲靜態文件提供。因此,大多數現代Perl框架都將static存儲在單獨的dir中,例如「public」。所以,你把所有的圖片,CSS,JS等在/公於以下方式配置Apache:

RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} -f 
RewriteRule ^(.*) public/$1 [L] 

RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f 
RewriteRule ^(.*) myapp.cgi [L] 

這個例子從Mojolicious documentation拍攝。

現在,如果用戶請求「public」中存在的內容並將所有其他請求重定向到您的應用,Apache將向用戶發送靜態文件。

在您的應用程序中,您需要將某些請求分派給某些操作。實際上,你需要一個能爲你做這項工作的模塊。由Viacheslav Tykhanovskyi編寫的Routes::Tiny(也可在CPAN)是一個不錯的選擇。

畢竟,如果你想知道框架是如何工作的,爲什麼不潛入其中呢? Mojolicious和舞者太大了,但是你可以看看更小的東西,比如Lamework,它可以在PSGI協議上工作,現在它變成了標準。

+0

謝謝。雖然這不是一個完全的答案,但我指出了一個解決方案。 – GeneQ

+0

@GeneQ,我更新了我的答案。但是如果你想知道框架是如何工作的,那麼你真的需要看看其中的一個。 – yko

1

我強烈建議使用web開發框架。這需要一點點學習,但是到你完成的時候,你會意識到你目前的做法遠非理想。有許多簡單的框架可以讓你快速啓動和運行。我建議使用Dancer(www.perldancer.org)。在舞者中,設置路線就像下面的例子一樣簡單。

get'/'=> sub {'Hello world!'}

順便說一句,您希望使用CGI的可能性很小。 CGI通常表現非常差,基本上已經不存在。我建議你看看FastCGI和PSGI,它們都可以在Apache中找到。

+0

我正在學習編寫框架。我想表達他們的內部工作方式。 ;-) – GeneQ

1

您可以捕獲404錯誤並使用cgi腳本處理它。在您的頂級.htaccess文件(文檔根目錄/的.htaccess):

ErrorDocument 404 /cgi/my-script.sh 

然後在你的處理程序腳本(my-script.sh)原來的路徑將被作爲enviromnent變量REDIRECT_URL通過。但請確保您的處理程序腳本通過添加Status: 200 OK標頭來正確設置HTTP狀態。下面是一個示例CGI腳本(/cgi/my-script.sh):

#!/bin/sh 

echo Status: 200 OK 
echo Content-type: text/plain 
echo 
echo Your url was $REDIRECT_URL 

(我不建議使用Bourne shell的編寫CGI腳本,但它說明的方法)。

您也可以將ErrorDocument設置放入httpd.conf文件中,但是任何更改都需要重新啓動服務器;將它放在.htaccess中可以讓它在運行時更容易調整。

上自定義錯誤處理

阿帕奇參考:http://httpd.apache.org/docs/2.1/custom-error.html

如果您使用的mod_perl,它更容易和更清潔的(更不用提更好地進行)將其設置爲一個Perl處理器;再次在頂層.htaccess文件(或httpd.conf中):

SetHandler perl-script 
PerlHandler MyThing::HandlerPackage 

其中MyThing::HandlerPackage是定義適當handler子perl的模塊。

+0

啊,這就是它是如何完成的。這是我無法弄清楚的事情;如何掛鉤一個404錯誤的腳本。 – GeneQ