如何使用Catalyst和uri链接REST接口?

时间:2011-12-13 17:43:47

标签: perl catalyst

我期待收到像uri一样的

/user/*/account/*

我有一个定义为

的用户功能
sub user  :Path('/user') :PathPart('') :ActionClass('REST' ) {}

然后

sub user_GET :PathPart('user') Chained('/') CaptureArgs(1) {
    #do stuff

}

对于我同样定义它们的帐户。

 sub account :Path('/account') :PathPart('') :ActionClass('REST') {}

 sub account_GET :PathPart('account') Chained('user_GET') Args(1) {
     #do stuff
 }

所以,问题是当我将account_GET中的Chained设置为服务器的'user_GET'时 debug显示路径已设置:

[debug] Loaded Chained actions:
.-----------------------------+--------------------------------------.
| Path Spec                   | Private                              |
+-----------------------------+--------------------------------------+
| /user/*/account/*           | /mcp/user_GET (1)                    |
|                             | => /mcp/account_GET                  |
'-----------------------------+--------------------------------------'

当我将account_GET中的Chained设置为'user'时,服务器调试显示:

[debug] Unattached Chained actions:

[debug] Unattached Chained actions:

.-------------------------------------+--------------------------------------.
| Private                             | Missing parent                       |
+-------------------------------------+--------------------------------------+
| /mcp/account_GET                    | /mcp/user                            |
'-------------------------------------+--------------------------------------'

问题是,显然后者没有建立而前者是 回来说没找到。

所以问题是如果我正在调用/ user / 12345 / account / 23456我该如何获得该路径 当看起来很明显的路径时,链接('用户')没有正确设置 被设置和不太明显的路径,Chained('user_GET'),根本就没有用?

3 个答案:

答案 0 :(得分:4)

就个人而言,我会在用户控制器中使用以下内容:

package MyApp::Controller::User;
...
# root of the chain
sub object: Chained PathPart('user') CaptureArgs(1) { ... }

上面的object操作会将用户对象加载到存储中。现在我将用户控制器链接到上面,如下所示:

package MyApp::Controller::User::Account;
...
# chains to the action loading the user object and dispatches RESTy
sub account: Chained('/user/object') ActionClass('REST') Args(1) { ... }

# handle individual request methods
sub account_GET { ... }
sub account_POST { ... }

此处account操作为执行实际操作的account_*方法提供了公共数据。

将特定于方法的操作作为链的一部分(比如让useraccount操作的POST请求作出反应)从设计的角度看似乎有点违反直觉。这可能有用,但我从未尝试过。

以上示例当然是简化的。我通常在每个控制器中设置base动作,设置命名空间和公共父动作,控制器中的所有其他动作将链接该动作。然后我会在上面加object来加载单个资源,并为控制器的根操作设置root。由于您可以构建任何类型的树结构,因此它非常灵活。因此,最佳解决方案通常取决于您的约束条件。

答案 1 :(得分:3)

来自mst

#catalyst说:

  

_GET / _POST方法不需要调度属性

答案 2 :(得分:1)

我相信做类似下面的事情会有效,但你必须以某种方式传递链式参数,无论是在存储中,还是作为$ self中的对象属性。

sub base
    :Chained('/')
    :PathPart('')
    :CaptureArgs(0)
    {
    my ( $self, $c ) = @_;
}

sub user_account
    :Chained('/')
    :PathPart('user')
    :CaptureArgs(1)
    :ActionClass('REST')
    {
    my ( $self, $c, $user_id ) = @_;
}

sub user_account_GET
    :Chained('user')
    :PathPart('account')
    :Args(1)
    {
    my ( $self, $c ) = @_;
}

这是它创建的路径规范

[debug] Loaded Chained actions:
.-------------------------------------+--------------------------------------.
| Path Spec                           | Private                              |
+-------------------------------------+--------------------------------------+
| /user/*/account/*                   | /user/base (0)                       |
|                                     | -> /user/user_account (1)            |
|                                     | => /user/user_account_GET            |

:Chained('/')当然意味着链条的开始。 :Chained('user_account')基本上意味着在控制器中查找一个名为user_account的子程序,如果你放:Chained('/user_account')它将开始在根控制器中查找(这有点复杂因为你可以在根控制器之外建立全局链接。 :PathPart('foo')确定实际URI的组件。显然,您需要在中点使用:CaptureArgs(1),在结束点使用:Args(1)