【问题标题】:How to create common handler for all incoming URLs?如何为所有传入 URL 创建通用处理程序?
【发布时间】:2016-01-04 16:34:25
【问题描述】:

我正在编写一些 web api,它以 JSON 格式返回数据。

对于所有传入的 url,如果缓存期没有过期,我需要从缓存中返回一些结果。

此逻辑适用于所有 URL。

问题:

如何为 Mojolicious::Lite 中的所有传入 URL 实现一些通用逻辑?

我试过了

any '/:bar' => [bar => qr/.+/] => sub {
 # ...
 # Return JSON object immediately from cache if it is applicable
 # ...
}

但这会导致页面加载时间过长

Template "bar.html.ep" not found

在 morbo 日志中(但 get "/target" 处理程序将在很长的延迟后最终执行)。

我是 Mojo 的完美新手,因此将不胜感激任何帮助

谢谢!

【问题讨论】:

  • 你能告诉我们你的处理程序中的代码吗? Mojolicious 不应该寻找 html.ep 模板来返回 JSON。您的处理程序是否以 $self->render( json => $object ); 结尾?
  • 我想,mojolicio.us/perldoc/Mojolicious/Guides/Routing#Hooks 可能对我有帮助。但是精简版的 Mojo 是否支持它?..

标签: perl mojolicious mojolicious-lite


【解决方案1】:

是的,before_dispatch 钩子似乎是正确的方法,它确实适用于 Mojolicious::Lite。这是一个概念验证,它将为每个唯一请求生成一个新结果,但为重复请求返回重复结果。在这个程序中,常规请求处理程序会填充缓存,但如果您想将该部分与代码的主要功能分开,您可以在 after_dispatch 挂钩中进行缓存。

use Mojolicious::Lite;

our %CACHE;

any '/:any' => sub {
    my $self = shift;
    my $param = $self->param('any');
    my $result = { reqtime => time, param => $param, number => rand };
    my $path = $self->req->url->path->to_string;
    $CACHE{$path} //= $result;
    $self->render( json => $result );
};

app->hook( before_dispatch => sub {
    my $c = shift;
    my $path = $c->req->url->path->to_string;
    if (defined($CACHE{$path})) {
        $c->render( json => $CACHE{$path}, status => 200 );
    }
} );
app->secrets([42])->start;

示例运行:

$ morbo cachedemo.pl >/dev/null 2>&1 &

$ for req in foo foo1 foo2 foo3 foo foo1
> do curl http://localhost:3000/$req ; echo ; sleep 1 ; done

{"number":0.848003210075227,"reqtime":1444254617,"param":"foo"}
{"number":0.0745738560703799,"reqtime":1444254618,"param":"foo1"}
{"number":0.484934245556467,"reqtime":1444254619,"param":"foo2"}
{"number":0.181112856445004,"reqtime":1444254620,"param":"foo3"}
{"number":0.848003210075227,"reqtime":1444254617,"param":"foo"}     <-- dup
{"number":0.0745738560703799,"reqtime":1444254618,"param":"foo1"}   <-- dup

【讨论】:

  • 太棒了,非常感谢!我不知道 Perl 中的 "//=" 构造以及启动应用程序的可能性,例如 app->secrets(["somesecret"])->start ... 请告诉我,如何避免执行 after_dispatch在 before_dispatch 钩子中进行渲染后钩子?提前谢谢!
【解决方案2】:

您可以使用 * 占位符。看here

也把你的应用放到开发者mode:

Mojolicious->new( mode => 'developer' );
$app->mode( 'developer');

你会得到漂亮的 404、500 个页面,对你很有帮助

【讨论】:

    猜你喜欢
    • 2015-06-13
    • 2013-12-24
    • 2011-03-06
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 2012-07-31
    相关资源
    最近更新 更多