Category Archives: Perl

Perl related techniques

用 Catalyst 做簡單 proxy 時,資料被 Truncate 的問題

Catalyst 是一套以 PERL 寫成的 Framework,自從去年聽了 gugod 的介紹之後開始接觸,關於更進一步的介紹可以參考他做的投影片

前兩天試著用 Catalyst 做一個簡單的 Reverse Proxy Server;基本的流程就是:當 user 送 request 過來,到另一台 server 去把檔案抓回來,並且回傳給 client 端;流程很簡單,但是不知道為什麼,在圖檔的部份時好時壞,特定的檔案會無法正確顯示。檢查之後發現,這些檔案在快要傳完時, server 就把 connection 截斷,因此就會一直重傳。

原本的寫法如下:

my $user_agent = LWP::UserAgent->new();
my $respond = $user_agent->get($url);
if ($respond->is_success()) {
$context->res->content_type($respond->content_type());
$context->res->content_length($respond->content_length());
$context->res->content_encoding($respond->content_encoding());
$context->res->output($respond->content());}
return 1;

經過一番努力交叉測試之後,發現上面粗體字的那行,必須要改成

$context->res->write($respond->content());

才行,這樣就不會有問題了,原因不明,如果有人知道為什麼的話,還請指教啊~

Update: 發現原來是我白爛。原本的寫法是沒有問題的,問題是出在原本設定了一個 default End handler,是會自動把 user 已經填過的表單填好,結果沒有檢查是不是已經有資料,一樣丟進去處理,於是就會有這個問題。正確的寫法如下:

sub end : Private
{
my ($self, $context) = @_;
$context->forward('FindBook::View::TToolkit') unless $context->res->output; $context->fillform( ) unless $context->res->output;
}

不是 aPen,是 cPan — 用 FindBin 設定程式的路徑

大大名言:「aPen 少看點, cPan 多看點」,今天來介紹這個 FindBin Module。

寫程式時,建立 libaray 是個好習慣,在 Perl 下面如果寫成 Perl Module 當然是最好了,可是辛苦寫好的 Perl Module,有時候沒辦法放進標準的 Include Path 目錄中,有時候是想要和程式本身一起流傳,那這時候要怎麼辦呢?

利用 use lib LIB_PATH 可以在 @INC 中加入 Module 的路徑,這樣程式就可以找到自己加入的 Module 了,例如:

use lib ‘/home/pesty/myperl/lib’;

這樣是不錯啦,可是把路徑寫死在程式裡面,總是覺得怪怪的;而且,將來程式要傳給別人,也很不方便。有些人,就像我,就想把 use lib 後面的參數改成變數,結果就會遇到這樣的 error:

Empty compile time value given to use lib at ./lib_path.pl

原來 lib 是不能指定 variable 的,後來才找到原來可以用 FindBin 這個 Module 來避開這個問題;FindBin 會找出現在程式執行的絕對路徑,把這個資訊存到 $FindBin 裡面去,所以用 $FindBin::Bin 就可以取得現在的程式路徑,更棒的是這個變數還可以拿來指定 @INC 的資訊:

#!/usr/bin/perl

use FindBin;
use lib “$FindBin::Bin/../lib”;

use MyApp::Module;

藉著這樣,就可以把自定的 Perl Module 丟到 MyApp/lib, 執行檔丟到 MyApp/bin 之類的,以後只要把 MyApp 整個包起來就可以移到別的地方也沒問題了。

關於 FindBin 的進一步說明,請參考 CPAN : FindBin,今天的 CPAN 教室就到這裡,大家可以回去看 aPen 了。