2015-10-07 6 views
5

Я в процессе написания некоторых веб-api, который возвращает данные в формате JSON.Как создать общий обработчик для всех входящих URL-адресов?

Для всех входящих URL-адресов мне нужно вернуть некоторый результат из кеша, если период кеша не истекает.

Эта логика является универсальной для всех URL-адресов.

Вопрос:

Как реализовать некоторую общую логику для всех входящих URL-адресов в Mojolicious :: Lite?

Я пытался сделать

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

Но это приводит к очень длинную загрузку страниц и

Template "bar.html.ep" not found 

в журнале Морбо (но получить «/ мишень» обработчик будет выполняться в конце концов, после того, как долго задержка).

Я совершенный новичок в Mojo, так что любая помощь будет оценена

Спасибо!

+3

Можете ли вы показать нам код в обработчике? Mojolicious не должен искать шаблон 'html.ep' для возврата JSON. Ваш обработчик заканчивается '$ self-> render (json => $ object);'? – mob

+0

Я думаю, http://mojolicio.us/perldoc/Mojolicious/Guides/Routing#Hooks могут мне помочь. Но поддерживает ли Lite версия Mojo? .. – drvtiny

ответ

2

Да, a 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.075227,"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.075227,"reqtime":1444254617,"param":"foo"}  <-- dup 
{"number":0.0745738560703799,"reqtime":1444254618,"param":"foo1"} <-- dup 
+0

Удивительно, спасибо вам большое! Я не знал о конструкции «// =» в Perl и о возможности запуска приложения просто как app-> secrets ([«somesecret»]) -> start ... Не могли бы вы рассказать мне, пожалуйста, как избежать выполнения after_dispatch крюк после выполнения рендеринга в hook_Add_dispatch? Заранее спасибо! – drvtiny

1

вы можете использовать * заполнитель. Посмотрите here

также поместить ваше приложение в разработчика mode:

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

вы получите довольно 404, 500 страниц, которые помогут вам очень

Смежные вопросы