跳转到内容

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://127.0.0.1/'),
    env => \%ENV,
    connection_info => {
        request_uri => "/"
    }
);

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

如果比较了$engine对象的构造语句,您会发现唯一的区别是“module”值。这个“Test”模块使$engine对象成为一个完全模拟的环境,它基本上只是准备了所有需要的环境变量,并执行您的应用程序代码。

这使得它非常轻量级,易于运行和编写测试程序。然后,您可以像编写单元测试一样编写功能测试。


前一个:HTML::Mason 索引 下一个:PSGI
华夏公益教科书