简体   繁体   English

如何在 Perl 中实现 RESTful API?

[英]How can I implement a RESTful API in Perl?

I'm trying to implement a RESTful API in Perl.我正在尝试在 Perl 中实现一个 RESTful API。 My current idea is to simply parse the path_info with a regex then dispatch the request to the appropriate subroutine which will then spit out the JSON, XML or even XHTML for the requested resource.我目前的想法是简单地使用正则表达式解析 path_info,然后将请求分派到适当的子程序,然后该子程序将为请求的资源吐出 JSON、XML 甚至 XHTML。

For example to retrieve info about user 1234 the RESTful client should find it at:例如,要检索有关用户 1234 的信息,RESTful 客户端应在以下位置找到它:

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

Below is the skeleton code of my first attempt at implementing a RESTful API:下面是我第一次尝试实现 RESTful API 的框架代码:

model.pl :模型.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");
}

Before I proceed any further, I would like to hear from experienced Perl hackers whether I got the basic idea right and if there are any serious shortcomings with this approach in terms of performance.在我继续之前,我想听听经验丰富的 Perl 黑客的意见,我的基本想法是否正确,以及这种方法在性能方面是否存在任何严重缺陷。

I can imagine, after a while, the if/else block would grow really large.我可以想象,一段时间后,if/else 块会变得非常大。

Looking forward to hear your views to make this code better.期待听到您的意见,以使此代码更好。

For lightweight REST APIs I would look at Mojolicious.对于轻量级 REST API,我会查看 Mojolicious。 The request routing is really straightforward and the inbuilt JSON renderer and user agent make development of simple REST APIs very straightforward in my experience.根据我的经验,请求路由非常简单,内置的 JSON 渲染器和用户代理使简单 REST API 的开发变得非常简单。

If your app is going to be relatively small then Mojo::Lite may suit your requirements.如果您的应用程序相对较小,那么Mojo::Lite可能会满足您的要求。 For example you may be able to do something like this:例如,您可以执行以下操作:

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;

I would use something like CGI::Application::Dispatch, it lets me build a dispatch table with variables and REST methods, and lets you use CGI and CGI::Application modules from CPAN.我会使用像 CGI::Application::Dispatch 这样的东西,它让我用变量和 REST 方法构建一个调度表,并让你使用 CPAN 中的 CGI 和 CGI​​::Application 模块。 Eg:例如:

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' },
],

(or you can use auto_rest or auto_rest_lc) (或者您可以使用 auto_rest 或 auto_rest_lc)

you can use a separate CGI::Application class for each type of thing (or just use classes in your cgi-app controller class methods).您可以为每种类型的事物使用单独的 CGI::Application 类(或仅在您的 cgi-app 控制器类方法中使用类)。

CGI::Application also comes with plugins for outputting XML, JSON or text generated from templates. CGI::Application 还带有用于输出 XML、JSON 或从模板生成的文本的插件。

cgi-app (and c::a::d) are are CGI applications and can be used with (little or) no change under CGI, FastCGI or mod_perl. cgi-app(和 c::a::d)是 CGI 应用程序,可以在 CGI、FastCGI 或 mod_perl 下使用(很少或)没有更改。 C::A::D is also a mod_perl PerlHandler by default too. C::A::D 默认也是一个 mod_perl PerlHandler。

我会使用CatalystCatalyst::Controller::REST构建应用程序

Why not use the already implemented module Apache2::REST ?为什么不使用已经实现的模块Apache2::REST It is all there.它就在那里。

The simple solution:简单的解决方案:

 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;
 }

I know this has been a long time since this question has been asked, but I would like to provide some updated information.我知道自从提出这个问题以来已经很长时间了,但我想提供一些更新的信息。

There is a very useful module called Net::API::REST using Apache2 mod_perl behind.后面有一个非常有用的模块,名为Net::API::REST,使用 Apache2 mod_perl。

You just need to set up Apache, and create your own module inheriting from Net::API::REST and create an init method in which you define your endpoints map, such as:您只需要设置 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 );
}

And when someone access one of your endpoint, your corresponding method gets called in the context of a powerful environment to use to reply to the request.当有人访问您的端点之一时,您的相应方法将在强大环境的上下文中被调用,以用于回复请求。 Check the module metacpan page for more information.查看模块 metacpan 页面以获取更多信息。

The Simple Solution - with a variable tweak on $data using qq~~;简单的解决方案 - 使用qq~~;$data进行变量调整qq~~; Keeps all code lined up.保持所有代码对齐。

 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;
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM