1

我需要声明一个可以处理两种请求的路由:

GET /api/vote/:value 
GET /api/vote/:value/:date

在这两种情况下,我处理数据的方式并没有什么不同,所以我希望它们在同一个地方定义。

我现在所做的是我使用了一个通配符占位符

use Mojolicious::Lite -signatures;
use DateTime;

get '/vote/*values' => sub ($c) {
    my $datetime = DateTime->now;
    # Then we process the route parameters
    my @params = split('/', $c->param('values'), 2);
     # Optional if no date provided in the route
    if ( defined $params[1] ) {
        my @dates_params = split('-', $params[1], 3);
        my %datetime = (
            year  => $dates_params[0],
            month => $dates_params[1],
            day   => $dates_params[2],
        );
        $datetime =  DateTime->new(%datetime);
    }
    my %vote = (
        value => $params[0],
        datetime => $datetime,
    );
    # ... More code here
    $c->render(json => $data);
}

它以这种方式工作得很好,但我对这个解决方案不太满意,因为它不是很明确也不可读,而且我知道其他框架允许以看起来更令人满意的方式做类似的事情。

例如,以下使用Express.js 路由功能/vote/123/vote/123/2019-01-13只允许在一个路由声明中到达。

router.get('/vote/:value/:date*?', function(req, res, next) {
    // Processing here...
    res.json(// etc.);
});

注意:这个例子来自这个 SO question

在尝试了各种可能性之后Mojolicious::Lite,我发现 Mojolicious 路由中的正则表达式不是一个东西,我发现最好的解决方案是通配符占位符。我错过了什么吗?

4

1 回答 1

3
% mojo generate lite_app optional
...
% $EDITOR optional

可以通过给它一个默认值来将日期标记为可选undef

#!/usr/bin/env perl
use Mojolicious::Lite -signatures;

get '/vote/:value/*when' => { when => undef } => sub ($c) {
    my $value = $c->stash('value');
    my $when  = $c->stash('when');
    $c->render(
        format => 'txt',
        text   => $value . ' ' . ( defined $when ? $when : 'nope' ) . "\n"
    );
};

app->start;

然后允许有或没有日期查询:

% ./optional get /vote/42 2>/dev/null
42 nope
% ./optional get /vote/42/2020/01/07 2>/dev/null
42 2020/01/07
% 
于 2019-02-15T16:35:53.667 回答