如何将 /doc/ 添加到 Catalyst 中每个 URL 的末尾?

发布于 2024-07-15 00:18:09 字数 1995 浏览 7 评论 0原文

我们试图让我们的 REST API 更加友好,我们有一个 REST API 的基类,它继承自 Catalyst::Controller::REST。 每个 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/”之间有多少路径部分。

我缺少什么?

We're trying to make our REST API a bit more friendly, We have a base class for our REST API which inherits from Catalyst::Controller::REST. Each REST class can identify the query parameters it accepts. We thought it would be nice to make this information public and put this into the base class:

sub doc : Regex('/doc

And from there, every REST url could have /doc/ added to the end to show which query parameters it accepts.

It doesn't work. $self is always a PIPs::C::API::V1::Franchise instance, no matter which URL is called. This appears to be because of these:

[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          |

And:

[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                  |

So the very first instance of the "doc" method dispatches through Franchise, even if the controller for a given URL would be API::V1::Version or something like that.

How can I work around this? LocalRegex doesn't work, obviously, and chained actions don't seem appropriate because, due to the nature of our app, we never know how many path parts will be between '/api/v1/' and '/doc/'.

What am I missing?

) { my ( $self, $c ) = @_; $c->stash->{params} = $c->forward('allowed_query_params'); }

And from there, every REST url could have /doc/ added to the end to show which query parameters it accepts.

It doesn't work. $self is always a PIPs::C::API::V1::Franchise instance, no matter which URL is called. This appears to be because of these:

And:

So the very first instance of the "doc" method dispatches through Franchise, even if the controller for a given URL would be API::V1::Version or something like that.

How can I work around this? LocalRegex doesn't work, obviously, and chained actions don't seem appropriate because, due to the nature of our app, we never know how many path parts will be between '/api/v1/' and '/doc/'.

What am I missing?

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

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

发布评论

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

评论(4

才能让你更想念 2024-07-22 00:18:09

看起来,这取决于您想让您的应用程序变得多么优雅。 您可以尝试使用链接操作,将 doc 操作链接到您想要附加“/doc”的每个操作。 AFAIK,催化剂不支持将一个操作链接到多个其他操作,但这可能已经改变。
或者,他们不能都提出一个额外的论点吗?

或者,修改上面的代码:

sub auto : Private {
    my ($self, $c) = @_;
    if ((my $path = $c->req->path) =~ /\/doc$/) {
        $path =~ s/\/doc//;
        $c->detach($path);
    }
}

不过,这可能确实是不好的做法......

It depends on how elegant you want to make your application, it seems. You might try something with chained actions, chaining the doc action to every action that you'd like to append '/doc' to. AFAIK, catalyst does not support chaining an action to multiple other actions, but that may have changed.
Alternatively, could they not all take one additional argument?

Or, modifying the code above:

sub auto : Private {
    my ($self, $c) = @_;
    if ((my $path = $c->req->path) =~ /\/doc$/) {
        $path =~ s/\/doc//;
        $c->detach($path);
    }
}

That's really probably poor practice, though...

§普罗旺斯的薰衣草 2024-07-22 00:18:09

我认为您需要 LocalRegex 而不是 Regex。 但为什么要使用正则表达式,而不仅仅是简单的 Local 呢?

I think you want LocalRegex instead of Regex. But why a regex at all, and not just plain Local?

献世佛 2024-07-22 00:18:09

您可以执行此根站点文件(如果站点名为 Hello,则在 lib 文件夹中为 Hello.pm)。 您可以使用方法prepare_path并检查第一部分是否为api/v1,以将文档部分附加到末尾。 不确定现阶段这样做是否是不好的做法。

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

You can do this root site file (Hello.pm in the lib folder if the site is called Hello). You can use the method prepare_path and check if the first part is api/v1 to append the doc part to the end. Not sure if it is bad practice to do it at this stage.

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 ) ;
   }
 }
谜兔 2024-07-22 00:18:09

我认为 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->;最后添加 doc 的路径或 $c->req->args ,然后转发到相关的私有操作(如果存在

sub auto : Private {
    my ($self, $c) = @_;
    $c->forward('doc_method) if $c->req->args->[ $@{$c->req->args}  eq 'doc';
}

)(未经测试)。 同样,您可能想要 $c->detach 而不是转发,不确定。

I think Local won't work because the controller action might accept several arguments, so Controller::Foo::my_action might end up accepting: /foo/my_action/this/1/that/2/the_other

So if I'm reading you correctly you want /foo/my_action/this/1/that/2/the_other/doc,
/bar/other_action/thing/4/thang/2/the_other/doc etc.

Well one way of doing it would be to have a sub auto : Private { } in a base controller that checks $c->req->path or $c->req->args for doc at the end and then forwards to the relevant private action if it's there

sub auto : Private {
    my ($self, $c) = @_;
    $c->forward('doc_method) if $c->req->args->[ $@{$c->req->args}  eq 'doc';
}

(untested). Aslo you may want $c->detach rather than forward, not sure.

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