Как объявить путь маршрута с необязательным заполнителем в Mojolicious::Lite?

Мне нужно объявить маршрут, который мог бы обрабатывать два типа запросов:

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.

Попробовав различные возможности с Mojolicious::Lite, я обнаружил, что регулярные выражения в маршрутах Mojolicious не нужны, и лучшим решением, которое я нашел, был заполнитель подстановочных знаков. Я что-то упускаю?


person smonff    schedule 13.01.2019    source источник


Ответы (1)


% 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
% 
person thrig    schedule 15.02.2019