Как объявить путь маршрута с необязательным заполнителем в Mojolicious::Lite?
Мне нужно объявить маршрут, который может обрабатывать два вида запросов:
GET /api/vote/:value
GET /api/vote/:value/:date
То, как я отношусь к данным, в обоих случаях не сильно отличается, поэтому я бы хотел, чтобы они были определены в одном и том же месте.
На данный момент я использовал заполнитель wilcard:
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 - это не вещь, и лучшим решением, которое я нашел, был шаблонный заполнитель. Я что-то пропустил?
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
%