跳轉到內容

Perl 程式設計/HTTP::Engine

來自華夏公益教科書,開放的書籍,為開放的世界
前一個:HTML::Mason 索引 下一個:PSGI


HTTP::Engine

[編輯 | 編輯原始碼]

HTTP::Engine由 Kazuhiro Osawa (yappo) 建立。它是一個針對應用程式開發人員的通用介面,可以輕鬆地在各種伺服器配置下部署,包括 CGI、FastCGI、mod_perl以及獨立的純 Perl HTTP 伺服器。然而,它不是一個完整的 Web 應用程式框架,但基於它編寫框架會很容易。

一個應用程式核心,多個介面

[編輯 | 編輯原始碼]

例如,這是一個簡單的應用程式,它只輸出“Hello World”

# MyApp.pm
package MyApp;
use strict;
use warnings;

use HTTP::Engine::Response;

sub run {
  my ($class, $request) = @_;
  my $response = HTTP::Engine::Response->new;

  $response->body("Hello World");
  $response->status(200);

  return $response;
}

1;

run方法在這裡接受一個HTTP::Engine::Request例項作為輸入,並返回一個HTTP::Engine::Response物件作為輸出。這個子程式是來自 HTTP 伺服器的第一個處理程式。在一個更復雜的應用程式中,它通常只是根據 URI 或引數將實際工作分派給其他子程式。

要將其部署為 CGI 指令碼,您需要編寫一個“hello.cgi”就像這樣

#!/usr/bin/perl
use MyApp;
use HTTP::Engine;

HTTP::Engine->new(
    interface => {
        module => 'CGI',
        request_handler => sub {
            MyApp->run(@_);
        }
    }
)->run;

如果有一天,你需要在這個應用程式下部署mod_perl環境,你可以編寫一個MyApp::ModPerl處理程式類,程式碼如下

package MyApp::ModPerl;
use Any::Moose;
extends 'HTTP::Engine::Interface::ModPerl';

use MyApp;
use HTTP::Engine;

sub create_engine {
    my($class, $r, $context_key) = @_;

    HTTP::Engine->new(
        interface => {
            module => "ModPerl",
            request_handler => sub {
                MyApp->run(@_);
            }
        }
    );
}

__PACKAGE__->meta->make_immutable;
no Any::Moose;
1;

您的核心應用程式程式碼不需要修改,只要您只使用HTTP::Engine::*類來構建您的響應。

您可能會質疑為什麼費心建立一個抽象層,而不是直接選擇一個好的部署環境。一個很好的答案是,沒有這個抽象層,可能很難測試應用程式。

如果您的首選部署配置類似於mod_perl,那麼您的測試程式將需要啟動一個帶有mod_perl.so載入的 apache httpd,然後嘗試使用Test::WWW::Mechanize與它通訊。這也可以,但太麻煩了。

HTTP::Engine附帶了一個專門的測試介面,可以輕鬆完成此操作。要測試我們的“Hello World”應用程式是否正常工作,您可以編寫一個像這樣的測試程式

# test.pl
use strict;
use warnings;

use Test::More tests => 1;

use MyApp;
use HTTP::Engine;
use HTTP::Request;
use HTTP::Response;

my $engine = HTTP::Engine->new(
    interface => {
        module => 'Test',
        request_handler => sub {
            return MyApp->run(@_);
        }
    }
);

my $response = $engine->run(
    HTTP::Request->new(GET => 'https:///'),
    env => \%ENV,
    connection_info => {
        request_uri => "/"
    }
);

is($response->content, "Hello World", "The application does output Hello World!");

如果比較了$engine物件的構造語句,您會發現唯一的區別是“module”值。這個“Test”模組使$engine物件成為一個完全模擬的環境,它基本上只是準備了所有需要的環境變數,並執行您的應用程式程式碼。

這使得它非常輕量級,易於執行和編寫測試程式。然後,您可以像編寫單元測試一樣編寫功能測試。


前一個:HTML::Mason 索引 下一個:PSGI
華夏公益教科書