Perl REST 流程布局

发布于 2024-07-25 14:07:00 字数 467 浏览 8 评论 0原文

我正在使用 Apache 和 Perl (modperl),以及处理程序来处理请求。 我对此很陌生,我不太确定如何以合理的方式安排事情。

现在我有以下问题:

package MyClass::Handler;

use warnings;
use strict;
# includes

our %action = ( 
   'a' => \&a,
   # And more
);

sub handler {
    my $a = shift;
    my $r = Apache2::Request->new($a);

    # Do things

    return Apache2::Const::OK();
}

我应该为每个“空间”有一个不同的文件吗? 使用 stackoverflow 作为模板,我是否需要 User.pm 来进行所有用户管理? 故事的 Story.pm?

I'm using Apache and Perl (modperl), with Handlers to handle requests. I'm new to this, and I'm not quite sure how to lay things out in a sensible way.

Right now I have the following:

package MyClass::Handler;

use warnings;
use strict;
# includes

our %action = ( 
   'a' => \&a,
   # And more
);

sub handler {
    my $a = shift;
    my $r = Apache2::Request->new($a);

    # Do things

    return Apache2::Const::OK();
}

Should I have a different file for each "space"? Using stackoverflow as a template, do I need a User.pm for all the User management? A Story.pm for stories?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鲜血染红嫁衣 2024-08-01 14:07:00

您可能对优秀的 CGI::Application 感兴趣 来自 CPAN 的框架。 尽管它的名字如此,但它在普通 CGI 和 mod_perl 下都可以工作。 它旨在使设置 Web 应用程序调度表的任务变得非常简单。 加入 CGI::Application: :Dispatch 你会得到漂亮的类似 REST 的 URL。

You might be interested in the excellent CGI::Application framework from CPAN. Despite its name, it works both under normal CGI and mod_perl. It's designed to make the task of setting up web-app dispatch tables very simple. Throw in CGI::Application::Dispatch and you get nice REST-like URLs.

猫九 2024-08-01 14:07:00

对于最近的项目,我编写了一个自定义配置处理程序,它实现了新的 ResourceURI 配置设置。 这让我可以将配置行放入 httpd.conf 中,如下所示:

ResourceURI SomeResource GET,POST,DELETE "^/...$"

三个参数是我的资源类名称、资源可以响应的 HTTP 方法列表以及与资源的 URI 匹配的正则表达式。

自定义配置类用这样的块替换每一行:

PerlModule Handler::{resource class}
PerlModule Resource::{resource class}

<Location ~ "{uri regex}">
    Order allow,deny
    Allow from all

    <LimitExcept {allowed methods}>
        Order deny,allow
        Deny from all
    </LimitExcept>

    SetHandler modperl
    PerlHandler Handler

    PerlSetVar Resource {resource class}
</Location>

这负责加载我的类,让 Apache 拒绝无效方法,设置一个标志来指示要路由到哪个资源,并通过我的 Handler::handler 传递所有请求() 功能。

package Handler;

sub handler {
    my $r = shift;
    my $resource_class = 'Resource::' . $r->dir_config('Resource');
    my $handler_class = 'Handler::' . $r->dir_config('Resource');
    my $resource = $resource_class->new($r, $r->uri);
    return Apache2::Const::HTTP_NOT_FOUND unless $resource;
    my $method = $r->method();
    return Apache2::Const::HTTP_NOT_IMPLEMENTED
        unless $handler_class->can($method);
    return $handler_class->$method($r, $resource);
}

现在您只需要使用资源逻辑(包括如何格式化表示)来实现 Resource::* 类,以及具有名为 GET、HEAD、POST 等方法的 Handler::* 类,并让它们使用 $r 和 $resource 来处理的请求。

对于您需要的每一个新资源,您添加一行配置,实现一个 Handler 类(我发现它通常是一个从通用基类继承的几乎空的模块),并实现一个包含大部分资源的 Resource 类。代码。 我还发现我经常需要在处理对另一种资源的请求的上下文中创建一个资源对象; 这就是为什么我的资源构造函数为 uri 采用单独的参数,而不是仅仅从 $r 获取 uri。 如果我在 Resource::Foo 中并且需要一个 Resource::Bar 对象,我可以说 my $bar = Resource::Bar->new($r, '/bars/1234'); 它使用客户端使用的相同 URI 创建 Bar 对象。

For a recent project, I wrote a custom configuration handler which implemented a new ResourceURI config setting. This let me put configuration lines into httpd.conf like this:

ResourceURI SomeResource GET,POST,DELETE "^/...$"

The three arguments are my resource class name, the list of HTTP methods which the resource can respond to, and a regex that matches the URI(s) for the resource.

The custom configuration class replaces each of these lines with a block like this:

PerlModule Handler::{resource class}
PerlModule Resource::{resource class}

<Location ~ "{uri regex}">
    Order allow,deny
    Allow from all

    <LimitExcept {allowed methods}>
        Order deny,allow
        Deny from all
    </LimitExcept>

    SetHandler modperl
    PerlHandler Handler

    PerlSetVar Resource {resource class}
</Location>

This takes care of loading my classes, lets Apache reject invalid methods, sets a flag to indicate which resource to route to, and passes all requests through my Handler::handler() function.

package Handler;

sub handler {
    my $r = shift;
    my $resource_class = 'Resource::' . $r->dir_config('Resource');
    my $handler_class = 'Handler::' . $r->dir_config('Resource');
    my $resource = $resource_class->new($r, $r->uri);
    return Apache2::Const::HTTP_NOT_FOUND unless $resource;
    my $method = $r->method();
    return Apache2::Const::HTTP_NOT_IMPLEMENTED
        unless $handler_class->can($method);
    return $handler_class->$method($r, $resource);
}

Now you just need to implement Resource::* classes with your resource logic (including how to format representations), and Handler::* classes with methods named GET, HEAD, POST, etc and have them use $r and $resource to handle the requests.

For every new resource you need, you add one line of configuration, implement one Handler class (which I've found can often be an almost empty module inheriting from a generic base class), and implement one Resource class which contains the bulk of the code. I've also found that I often need to create one resource object in the context of handling a request for another resource; that's why my resource constructors take a separate argument for the uri instead of just getting the uri from $r. If I'm in Resource::Foo and I need a Resource::Bar object, I can say my $bar = Resource::Bar->new($r, '/bars/1234'); which creates the Bar object using the same URI that a client would use.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文