FCGI::Buffer - 驗證、快取和最佳化 FCGI 輸出
版本0.19
FCGI::Buffer 透過HTML::Lint
傳遞來驗證您產生的 HTML。
FCGI::Buffer 透過減少、過濾和壓縮輸出來加速傳輸以及幾乎無縫地利用客戶端和伺服器快取來最佳化 FCGI 程式。
要利用客戶端緩存,也就是說,減少對伺服器請求相同資料的不必要的呼叫:
use FCGI;
use FCGI::Buffer;
# ...
my $request = FCGI::Request();
while($request->FCGI::Accept() >= 0) {
my $buffer = FCGI::Buffer->new();
$buffer->init(
optimise_content => 1,
lint_content => 0,
);
# ...
}
為了也利用伺服器緩存,也就是說,當不同的客戶端請求您提供相同的資料時保存重新產生的輸出,您將需要建立一個快取。但這很簡單:
use FCGI;
use CHI;
use FCGI::Buffer;
# ...
my $request = FCGI::Request();
while($request->FCGI::Accept() >= 0) {
my $buffer = FCGI::Buffer->new();
$buffer->init(
optimise_content => 1,
lint_content => 0,
cache => CHI->new(driver => 'File')
);
if($buffer->is_cached()) {
# Nothing has changed - use the version in the cache
$request->Finish();
next;
# ...
}
}
若要暫時阻止使用伺服器端快取,例如在發布程式碼變更之前進行偵錯時,請將 NO_CACHE 環境變數設為任何非零值。這也將阻止 ETag 添加到標頭中。如果您在列印中遇到有關寬字元的錯誤,則表示您忘記在非 ASCII 字元上發出純 HTML。請參閱 HTML::實體。作為一種破解方法,您也可以使用 Text::Unidecode 刪除重音等,它效果很好,但並不是您真正想要的。
建立一個 FCGI::Buffer 物件。對每個 FCGI::Accept 執行下列其中一個操作。
設定各種選項並覆蓋預設值。
# Put this toward the top of your program before you do anything
# By default, generate_tag, generate_304 and compress_content are ON,
# optimise_content and lint_content are OFF. Set optimise_content to 2 to
# do aggressive JavaScript optimisations which may fail.
use FCGI::Buffer;
my $buffer = FCGI::Buffer->new()->init({
generate_etag => 1, # make good use of client's cache
generate_last_modified => 1, # more use of client's cache
compress_content => 1, # if gzip the output
optimise_content => 0, # optimise your program's HTML, CSS and JavaScript
cache => CHI->new(driver => 'File'), # cache requests
cache_key => 'string', # key for the cache
cache_age => '10 minutes', # how long to store responses in the cache
logger => $self->{logger},
lint_content => 0, # Pass through HTML::Lint
generate_304 => 1, # When appropriate, generate 304: Not modified
save_to => { directory => '/var/www/htdocs/save_to', ttl => 600, create_table => 1 },
info => CGI::Info->new(),
lingua => CGI::Lingua->new(),
});
如果沒有給予cache_key,則會產生一個可能不唯一的cache_key。 cache_key 應該是一個唯一值,這取決於瀏覽器設定的值。
快取物件將是一個能夠理解 get_object()、set()、remove() 和created_at() 訊息的對象,例如 CHI 物件。它用作伺服器端緩存,以減少重新運行資料庫存取的需要。
預設情況下,項目會在伺服器端快取中保留 10 分鐘。這可以透過請求中的cache_control HTTP 標頭覆蓋,並且可以透過init() 的cache_age 參數來變更預設值。
Save_to 功能可將動態頁面的輸出儲存到 htdocs 樹中,並用靜態鏈接替換指向該頁面的未來鏈接,以避免通過 CGI。 Ttl 設定為靜態頁面被視為活動的秒數,預設為 10 分鐘。如果設定為 0,頁面將永遠存在。要啟用 save_to,也必須給予 info 和 lingua 參數。當也提供快取時效果最佳。僅在保證輸出與給定參數集相同的情況下使用(啟用generate_304的標準相同)。您可以根據具體情況將其關閉,如下所示:
my $params = CGI::Info->new()->params();
if($params->{'send_private_email'}) {
$buffer->init('save_to' => undef);
}
Info 是一個可選參數,用於提供有關 FCGI 環境的信息,例如 CGI::Info 物件。
Logger 將會是一個理解 debug() 的對象,例如 Log::Log4perl 物件。
要產生last_modified標頭,您必須提供一個快取物件。
Init 允許傳遞選項的參考。所以這兩種方法都有效: use FCGI::Buffer; #...我的 $buffer = FCGI::Buffer->new(); $b->init(generate_etag => 1); $b->init({generate_etag => 1, info => CGI::Info->new() });
一般來說,透過引用傳遞更好,因為它向堆疊複製的內容較少。
如果您給 init() 一個緩存,然後再給cache => undef,則不再使用伺服器端快取。當您在建立 HTML 時發現錯誤情況並決定不再希望將輸出儲存在快取中時,這非常有用。
init 的同義詞,因歷史原因而保留。
如果允許伺服器在本機儲存結果,則傳回 true。這是傳回標頭中 X-Cache 的值。
如果輸出已緩存,則傳回 true。如果是,則表示 FCGI 腳本中所有昂貴的例程都可以繞過,因為我們已經將結果儲存在快取中。
# Put this toward the top of your program before you do anything
# Example key generation - use whatever you want as something
# unique for this call, so that subsequent calls with the same
# values match something in the cache
use CGI::Info;
use CGI::Lingua;
use FCGI::Buffer;
my $i = CGI::Info->new();
my $l = CGI::Lingua->new(supported => ['en']);
# To use server side caching you must give the cache argument, however
# the cache_key argument is optional - if you don't give one then one will
# be generated for you
my $buffer = FCGI::Buffer->new();
if($buffer->can_cache()) {
$buffer->init(
cache => CHI->new(driver => 'File'),
cache_key => $i->domain_name() . '/' . $i->script_name() . '/' . $i->as_string() . '/' . $l->language()
);
if($buffer->is_cached()) {
# Output will be retrieved from the cache and sent automatically
exit;
}
}
# Not in the cache, so now do our expensive computing to generate the
# results
print "Content-type: text/htmln";
# ...
霍恩 (Nigel Horne), <njh at bandsman.co.uk>
即使在產生大量不同輸出的腳本中,例如電子商務情況,FCGI::Buffer 也應該是安全的。然而,在這些頁面上,我強烈建議將generate_304設為0並發送HTTP標頭“Cache-Control:no-cache”。
使用範本時,請確保不要使用它輸出到 STDOUT,而是需要捕獲到變數中並列印它。例如:
my $output;
$template->process($input, $vars, $output) || ($output = $template->error());
print $output;
如果您使用 <!-- HIDING 技術,可能會產生有缺陷的 JavaScript。這是 JavaScript::Packer 中的錯誤,而不是 FCGI::Buffer 中的錯誤。
Mod_deflate 在壓縮輸出時可能會混淆這一點。確保 .pl 檔案的通貨緊縮已關閉:
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png|pl)$ no-gzip dont-vary
如果您請求壓縮輸出,然後在產生相同輸出的輸入上請求未壓縮輸出(反之亦然),則狀態將為304。不應該看到這種情況發生或因此遇到任何困難。
FCGI::Buffer 尚未針對 FastCGI 進行測試。
我建議加入 FCGI::Buffer 作為最後一個 use 語句,以便先清除它。特別是,如果您使用 Log::Log4perl,則應在 Log::Log4perl 之後載入它,以便在 FCGI::Buffer 發送 HTTP 標頭之後列印它產生的任何訊息;
Save_to 不理解 JavaScript 中的鏈接,這意味著如果您使用作為靜態頁面加載的自調用 CGI,它們可能會指向錯誤的位置。解決方法是避免在 JavaScript 中自呼叫 CGI
請向bug-fcgi-buffer at rt.cpan.org
報告任何錯誤或功能請求,或透過 http://rt.cpan.org/NoAuth/ReportBug.html?Queue=FCGI-Buffer 的 Web 介面報告。我會收到通知,然後當我進行更改時,您會自動收到有關您的錯誤的進展的通知。
由於 HTML::Lint 的限制,lint 操作僅適用於 HTML4。
CGI::Buffer、HTML::Packer、HTML::Lint
您可以使用 perldoc 指令來尋找該模組的文件。
perldoc FCGI::Buffer
您也可以在以下位置找到資訊:
RT:CPAN 的請求追蹤器
http://rt.cpan.org/NoAuth/Bugs.html?Dist=FCGI-Buffer
CPAN評級
http://cpan ratings.perl.org/d/FCGI-Buffer
搜尋CPAN
http://search.cpan.org/dist/FCGI-Buffer/
其中一些的靈感和程式碼是 Mark Nottingham 的 cgi_buffer:https://www.mnot.net/blog/2003/04/24/etags。
cgi_buffer 的許可證是:
"(c) 2000 Copyright Mark Nottingham <[email protected]>
This software may be freely distributed, modified and used,
provided that this copyright notice remain intact.
This software is provided 'as is' without warranty of any kind."
該程式的其餘部分版權所有 2015-2023 Nigel Horne,並根據以下許可證發布:GPL2