如何在Perl中实现RESTful API?

时间:2009-08-11 08:51:20

标签: perl rest

我正在尝试在Perl中实现RESTful API。我目前的想法是简单地用正则表达式解析path_info,然后将请求分派给适当的子例程,然后该子例程将为请求的资源吐出JSON,XML甚至XHTML。

例如,要检索有关用户1234的信息,RESTful客户端应该在以下位置找到它:

http://example.com/model.pl/users/1234

下面是我第一次尝试实现RESTful API的框架代码:

model.pl

#!/usr/bin/perl -w
use strict;
use CGI;

my $q = CGI->new();

print $q->header('text/html');

my $restfuluri  = $q->path_info;

if      ($restfuluri =~ /^\/(questions)\/([1-9]+$)/) { questions($1, $2); }
elsif   ($restfuluri =~ /^\/(users)\/([1-9]+$)/)     { users($1, $2); }


sub questions
{
      my $object = shift;
      my $value  = shift;

      #This is a stub, spits out JSON or XML when implemented.
      print $q->p("GET question : $object -> $value");
}

sub users
{
      my $object = shift;
      my $value  = shift;

      #This is a stub, spits out JSON or XML when implemented.
      print $q->p("GET user: $object -> $value");
}

在进一步讨论之前,我想听听有经验的Perl黑客是否理解我的基本想法,以及这种方法在性能方面是否有任何严重缺陷。

我可以想象,过了一会儿,if / else块会变得非常大。

期待听取您的意见,以使此代码更好。

8 个答案:

答案 0 :(得分:16)

对于轻量级REST API,我会看一下Mojolicious。请求路由非常简单,内置的JSON渲染器和用户代理使我的经验中的简单REST API开发变得非常简单。

如果您的应用程序相对较小,则Mojo::Lite可能符合您的要求。例如,您可以执行以下操作:

use Mojolicious::Lite;

get '/questions/(:question_id)' => sub {
    my $self = shift;
    my $result = {};
    # do stuff with $result based on $self->stash('question_id')
    return $self->render_json($result)
}

app->start;

答案 1 :(得分:8)

我会使用类似CGI :: Application :: Dispatch的东西,它允许我使用变量和REST方法构建一个调度表,并允许您使用CPAN的CGI和CGI :: Application模块。 E.g:

table => [
'/questions/:id[get]'    => { rm => 'get_question' },
'/users/:id[get]'        => { rm => 'get_user' }, # OR
':app/:id[post]'         => { rm => 'update' }, # where :app is your cgi application module
':app/:id[delete]'       => { rm => 'delete' },
],

(或者您可以使用auto_rest或auto_rest_lc)

您可以为每种类型的事物使用单独的CGI :: Application类(或者只使用cgi-app控制器类方法中的类)。

CGI :: Application还附带了插件,用于输出从模板生成的XML,JSON或文本。

cgi-app(和c :: a :: d)是CGI应用程序,可以在CGI,FastCGI或mod_perl下使用(很少或没有)。 C :: A :: D默认也是mod_perl PerlHandler。

答案 2 :(得分:1)

我使用CatalystCatalyst::Controller::REST

构建应用程序

答案 3 :(得分:1)

为什么不使用已经实现的模块Apache2::REST? 它就在那里。

答案 4 :(得分:0)

简单的解决方案:

 use CGI;

 my $page  = new CGI;

 if( $ENV{ 'REQUEST_METHOD' } eq 'GET' ){

    my $data = <<json;
    {
    "isbn" : "123456",
    "title" : "Programming Perl",
    "author" : "L. Wall"
     }
 json

     print $page->header('application/json');

     print $data;
 }

答案 5 :(得分:0)

我知道自提出这个问题以来已经有很长时间了,但是我想提供一些更新的信息。

后面有一个非常有用的模块,称为Net::API::REST,该模块使用Apache2 mod_perl。

您只需要设置Apache,并创建继承自Net::API::REST的模块,并创建一个init方法,即可在其中定义端点映射,例如:

sub init
{
    my $self = shift( @_ );
    $self->{routes} =
    {
    # e.g. your API version 1
    1 =>
        {
        'favicon.ico' => $self->curry::noop,
        auth =>
            {
            google =>
                {
                _handler => $self->curry::oauth_google,
                callback => $self->curry::oauth_google(callback => 1),
                },
            linkedin =>
                {
                _handler => $self->curry::oauth_linkedin,
                callback => $self->curry::oauth_linkedin(callback => 1),
                },
            },
        },
        stripe => $self->curry::stripe,
    };
    $self->{api_version} = 1;
    $self->{supported_api_versions} = [qw( 1 )];
    $self->{default_methods} = [qw( GET POST )];
    $self->{supported_methods} = [qw( DELETE GET HEAD OPTIONS POST PUT )];
    $self->{supported_languages} = [qw( en-GB en fr-FR fr ja-JP )];
    $self->SUPER::init( @_ );
    return( $self );
}

当某人访问您的端点之一时,将在功能强大的环境中调用您的相应方法,以用于答复请求。检查模块metacpan页面以获取更多信息。

答案 6 :(得分:-1)

简单解决方案-使用$dataqq~~;上进行变量调整,使所有代码保持对齐。

 use CGI;

 my $page  = new CGI;

 if( $ENV{ 'REQUEST_METHOD' } eq 'GET' ){

    my $data = qq~
        {
            "isbn" : "123456",
            "title" : "Programming Perl",
            "author" : "L. Wall"
        }
    ~;

     print $page->header('application/json');

     print $data;
 }

答案 7 :(得分:-3)