如何在 Perl 的 Catalyst 中匹配 /foo 而不是 /foo/?
我想匹配 /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"
I want to match /foo, but not /foo/ (where foo can be any string) or /
I tried a lot of things along these lines:
sub match :Path :Regex('^[a-z]+
But I cannot achieve what I need.
I don't believe the problem is with my regex, but because I want to handle a path without an argument:
For example, for /aab/c, I get from Catalyst:
[debug] "GET" request for "aab/c" from "192.168.1.100"
[debug] Path is "aab"
[debug] Arguments are "c"
)
sub match :Regex('^[a-z]+
But I cannot achieve what I need.
I don't believe the problem is with my regex, but because I want to handle a path without an argument:
For example, for /aab/c, I get from Catalyst:
)
sub match :Path :Args(1)
But I cannot achieve what I need.
I don't believe the problem is with my regex, but because I want to handle a path without an argument:
For example, for /aab/c, I get from Catalyst:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
No :Args 指定将意味着“任意数量的参数,0 或更大”。 这意味着在您的初始示例中,
/foo/bar
和/foo/bar/baz
是匹配的。 正则表达式本身不匹配的正则表达式后面的路径元素将作为操作的参数被吃掉。(那些告诉你有关正则表达式的事情并说“我不知道 Catalyst 但是”的人忽略了一点,正则表达式匹配器中的 $ 可以匹配在“/”之前,而不总是在 URL 的末尾,在 Catalyst 中,其余部分将用作参数。)
您将需要
:Args(0)
来实现您想要实现的目标,指定 0 个路径部分用作参数(因此/foo/bar
不匹配)。然而,快速测试
表明
/foo
和/foo/
都匹配,(但这更近了一步:/match/xyz
没有)。 Catalyst 在路径中特别对待“/”,所以我不确定您是否可以做得更好。No :Args specified will mean 'any number of arguments, 0 or greater'. This means that in your initial examples,
/foo/bar
and/foo/bar/baz
are matches. Path elements after the regex that the regex itself doesn't match will get eaten as arguments to the action.(People who are telling you things about your regexp and saying 'I don't know Catalyst but' are missing the point here that $ in a regexp matcher can match just before a '/', and not always at the end of the URL, in Catalyst. The rest is then used as arguments.)
You will require
:Args(0)
for what you're trying to achieve, specifying that 0 path parts are to be used as arguments (so/foo/bar
doesn't match).However, a quick test using
demonstrates that
/foo
and/foo/
both match, (but this is a step closer:/match/xyz
doesn't). Catalyst treats '/' specially in paths, so I'm not sure if you can do better than this.根据 文档,
如果您希望正则表达式仅在当前命名空间的根匹配,请尝试使用 LocalRegex 操作:
According to the docs,
If you want the regex to match only at the root of the current namespace, try using a LocalRegex action instead:
仅当没有其他更具体的操作可以处理请求时,Regex 或 LocalRegex 才会匹配。
您需要支持
sub lowermatch :Regex ('/([az]+)/([az]+)') { }
来捕获 /foo/bar 并适当处理它。 不过,您现有的存根不应捕获“/”。 这应该通过 Root->default或者,如果没有参数,您可以在现有子中 $c->forward,即:
希望有帮助。
Regex or LocalRegex will only match if there is no other more specific action that could handle the request.
You need to support
sub lowermatch :Regex ('/([a-z]+)/([a-z]+)') { }
to catch /foo/bar and handle it appropriately. Your existing stub shouldn't be catching '/' though. That should be going through to Root->defaultAlternatively you can $c->forward in your existing sub if there are no arguments, ie:
Hope that helps.
免责声明:我对 Catalyst 不熟悉; 这些是(Perl)正则表达式。
如果“foo”必须是字母数字,这将执行您想要的操作:
如果“foo”确实可以是任何内容,请改用它:
Disclaimer: I'm not familiar with Catalyst; these are (Perl) regexes.
If "foo" must be alphanumeric this will do what you want:
If "foo" can truly be anything, use this instead:
LocalRegex 操作可能适合您所描述的内容,但是如果您正在做这种事情,那么您就是在与 HTTP 规范作斗争。
LocalRegex actions are probably OK for what you describe, but you're fighting against the HTTP spec if you're doing this kind of thing.
我不知道 Catalyst,但根据阅读文档,您似乎想要
子匹配 :Regex('^[a-zA-Z]*$') {}
正则表达式如下所示:
I don't know Catalyst, but based on reading the docs it looks like you want
sub match :Regex('^[a-zA-Z]*$') {}
The regex breaks down like this:
这个答案可能不是您正在寻找的,但我只是想把它放在这里是为了完整性:我可能会使用像 ModRewrite 这样的东西来从 /foo/ 重定向到 /foo 变体。
This answer might not be what you're looking for, but I just want to put it in here for completeness sake: I would probably use something like ModRewrite to make a redirect from the /foo/ to the /foo variant.