[英]How can I implement a RESTful API in Perl?
我正在尝试在 Perl 中实现一个 RESTful API。 我目前的想法是简单地使用正则表达式解析 path_info,然后将请求分派到适当的子程序,然后该子程序将为请求的资源吐出 JSON、XML 甚至 XHTML。
例如,要检索有关用户 1234 的信息,RESTful 客户端应在以下位置找到它:
http://example.com/model.pl/users/1234
下面是我第一次尝试实现 RESTful API 的框架代码:
模型.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 块会变得非常大。
期待听到您的意见,以使此代码更好。
对于轻量级 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;
我会使用像 CGI::Application::Dispatch 这样的东西,它让我用变量和 REST 方法构建一个调度表,并让你使用 CPAN 中的 CGI 和 CGI::Application 模块。 例如:
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。
我会使用Catalyst和Catalyst::Controller::REST构建应用程序
为什么不使用已经实现的模块Apache2::REST ? 它就在那里。
简单的解决方案:
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;
}
我知道自从提出这个问题以来已经很长时间了,但我想提供一些更新的信息。
后面有一个非常有用的模块,名为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 页面以获取更多信息。
简单的解决方案 - 使用qq~~;
对$data
进行变量调整qq~~;
保持所有代码对齐。
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;
}
你为什么不使用 apache mod_rewrite?
重定向http://mysite.com/model.pl/users/1234 --> http://mysite.com/users.pl
重定向http://mysite.com/model.pl/q/5678 --> http://mysite.com/questions.pl
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.