Как я могу сопоставить / foo, но не / foo / в Perl's Catalyst? - PullRequest
1 голос
/ 26 апреля 2009

Я хочу сопоставить / foo, но не / foo / (где foo может быть любой строкой) или /

Я много чего перепробовал:

sub match :Path :Regex('^[a-z]+$')
sub match :Regex('^[a-z]+$')
sub match :Path :Args(1)

Но я не могу достичь того, что мне нужно.

Я не верю, что проблема в моем регулярном выражении, но потому что я хочу обработать путь без аргумента:

Например, для / aab / c я получаю от Catalyst:

[debug] "GET" request for "aab/c" from "192.168.1.100"
[debug] Path is "aab"
[debug] Arguments are "c"

Ответы [ 7 ]

2 голосов
/ 28 апреля 2009

Нет: указанные аргументы будут означать «любое количество аргументов, 0 или больше». Это означает, что в ваших первоначальных примерах /foo/bar и /foo/bar/baz являются совпадениями. Элементы пути после регулярного выражения, которым само регулярное выражение не соответствует, будут съедены в качестве аргументов действия.

(Люди, которые рассказывают вам что-то о вашем регулярном выражении и говорят «Я не знаю Catalyst, но», упускают здесь момент, когда $ в сопоставителе регулярного выражения может совпадать непосредственно перед символом «/», а не всегда в конце URL, в Catalyst. Остальное затем используется в качестве аргументов.)

Вам потребуется :Args(0) для того, что вы пытаетесь достичь, указав, что 0 частей пути должны использоваться в качестве аргументов (поэтому /foo/bar не соответствует).

Тем не менее, быстрый тест с использованием

sub match :LocalRegex('^[a-z]+$') :Args(0)

показывает, что /foo и /foo/ оба совпадают (но это на шаг ближе: /match/xyz нет). Catalyst обрабатывает '/' специально в путях, поэтому я не уверен, что вы можете сделать лучше, чем это.

2 голосов
/ 26 апреля 2009

Regex или LocalRegex будут совпадать только в том случае, если нет других более конкретных действий, которые могли бы обработать запрос.

Вам необходимо поддерживать sub lowermatch :Regex ('/([a-z]+)/([a-z]+)') { }, чтобы поймать / foo / bar и обработать его соответствующим образом. Ваша существующая заглушка не должна поймать '/', хотя. Это должно пройти через Root-> default

В качестве альтернативы вы можете $ c-> forward в существующей подпрограмме, если нет аргументов, например:

sub match :Regex ('/foo') {
    my ($self, $c, @args) = @_;
    $c->forward('noargs_action') unless @args;
    ...
}

Надеюсь, это поможет.

2 голосов
/ 26 апреля 2009

Согласно документам ,

Соответствия регулярному выражению действуют глобально, т. Е. Без ссылки на пространство имен, из которого оно называется ...

Если вы хотите, чтобы регулярное выражение совпадало только в корне текущего пространства имен, попробуйте вместо этого использовать действие LocalRegex:

sub match : LocalRegex('^[a-z]+$')
1 голос
/ 26 апреля 2009

Действия LocalRegex, вероятно, хороши для того, что вы описываете, но вы боретесь против спецификации HTTP, если вы делаете такие вещи.

1 голос
/ 26 апреля 2009

Отказ от ответственности: я не знаком с Catalyst; это (Perl) регулярные выражения.

Если «foo» должен быть буквенно-цифровым, это будет делать то, что вы хотите:

^\/\w*$

Если "foo" действительно может быть чем-либо, используйте это вместо:

^\/$|^\/.*[^\/]$
0 голосов
/ 14 сентября 2010

Этот ответ может быть не тем, что вы ищете, но я просто хочу поместить его здесь для полноты картины: я бы, вероятно, использовал что-то вроде ModRewrite для перенаправления с / foo / на / foo вариант.

0 голосов
/ 26 апреля 2009

Я не знаю Catalyst, но на основе чтения документов, похоже, что вы хотите

sub match: Regex ('^ [a-zA-Z] * $') {}

Регулярное выражение распадается следующим образом:

  • ^ совпадение сразу после корня (т. Е. /)
  • [a-zA-Z] * соответствует нулю или более символов a-z или A-Z
  • $ соответствует концу URL
...