我们正在尝试使我们的REST API更友好,我们有一个继承自Catalyst :: Controller :: REST的REST API的基类。每个REST类都可以识别它接受的查询参数。我们认为将这些信息公开并将其放入基类会很好:
sub doc : Regex('/doc$') {
my ( $self, $c ) = @_;
$c->stash->{params} = $c->forward('allowed_query_params');
}
从那里开始,每个REST URL都可以在末尾添加/ doc /以显示它接受的查询参数。
它不起作用。 $ self总是一个PIPs :: C :: API :: V1 :: Franchise实例,无论调用哪个URL。这似乎是因为:
[26 Feb 2009 15:07:40,509] [Catalyst.Dispatcher] [DEBUG] Loaded Private actions:
.-----------------------+--------------------------------------+--------------.
| Private | Class | Method |
+-----------------------+--------------------------------------+--------------+
...
| /api/v1/franchise/doc | PIPs::C::Api::V1::Franchise | doc |
和
[26 Feb 2009 15:07:40,514] [Catalyst.DispatchType.Regex] [DEBUG] Loaded Regex actions:
.--------------------------------------+--------------------------------------.
| Regex | Private |
+--------------------------------------+--------------------------------------+
| /doc$ | /api/v1/franchise/doc |
| /doc$ | /api/v1/version/doc |
| /doc$ | /api/v1/creditrole/doc |
| /doc$ | /api/v1/doc |
| /doc$ | /api/v1/segmentevent/doc |
| /doc$ | /api/v1/collection/doc |
| /doc$ | /api/v1/episode/doc |
因此,“doc”方法的第一个实例通过Franchise进行调度,即使给定URL的控制器是API :: V1 :: Version或类似的东西。
我该如何解决这个问题?显然,LocalRegex不起作用,链式动作似乎不合适,因为由于我们的应用程序的性质,我们永远不知道'/ api / v1 /'和'/ doc /'之间有多少路径部分。
我错过了什么?
答案 0 :(得分:1)
我认为你想要LocalRegex
而不是Regex
。但是为什么要使用正则表达式,而不仅仅是普通Local
?
答案 1 :(得分:1)
这取决于你想要制作应用程序的优雅程度。您可以尝试使用链式操作,将doc操作链接到您要追加'/ doc'的每个操作。 AFAIK,催化剂不支持将动作链接到多个其他动作,但可能已经改变。 或者,他们不是都可以再提出一个论点吗?
或者,修改上面的代码:
sub auto : Private {
my ($self, $c) = @_;
if ((my $path = $c->req->path) =~ /\/doc$/) {
$path =~ s/\/doc//;
$c->detach($path);
}
}
这可能是糟糕的做法,但是......
答案 2 :(得分:0)
您可以执行此根站点文件(如果站点名为Hello,则在lib文件夹中为Hello.pm)。您可以使用方法prepare_path并检查第一部分是否为api / v1以将doc部分附加到末尾。不确定在这个阶段做这件事是不好的做法。
sub prepare_path {
my $c = shift;
$c->maybe::next::method( @_ ) ;
# Get the path
my $path = $c->request->path;
if ((index($path, 'api/v1') > 0)) {
$path .= '/doc';
# Change the path
$c->request->path( $path ) ;
}
}
答案 3 :(得分:-1)
我认为Local无法正常工作,因为控制器操作可能会接受多个参数,因此Controller :: Foo :: my_action最终可能会接受:/ foo / my_action / this / 1 / that / 2 / the_other
所以,如果我正确地读你,你想要/ foo / my_action / this / 1 / that / 2 / the_other / doc, / bar / other_action / thing / 4 / thang / 2 / the_other / doc等。
这样做的一种方法是在基本控制器中有一个子auto:Private {},用于检查$ c-> req-> path或$ c-> req-> args for doc at结束,然后转发相关的私人诉讼,如果它在那里
sub auto : Private {
my ($self, $c) = @_;
$c->forward('doc_method) if $c->req->args->[ $@{$c->req->args} eq 'doc';
}
(未测试)。你可能想要$ c->分离而不是前进,不确定。