【问题标题】:Excluding directory from regex redirect从正则表达式重定向中排除目录
【发布时间】:2015-08-11 09:08:06
【问题描述】:

我希望将所有带下划线的 URL 重定向到它们的等效虚线。

例如/nederland/amsterdam/car_rental 变为 /nederland/amsterdam/car-rental。为此,我使用了这里描述的技术:How to replace underscore to dash with Nginx。所以我的位置块匹配到:

location ~ (_) 

但我想对/admin 命名空间中的网址执行此操作。为了做到这一点,我尝试将正则表达式与否定查找结合起来:Regular expression to match a line that doesn't contain a word?。该位置现在匹配:

(?=^(?!\/admin))(?=([^_]*))

Rubular 报告字符串 /nederland/amsterdam/car_rental 以匹配正则表达式,而 /admin/stats_dashboard 不匹配,正如我想要的那样。但是,当我将此规则应用于 nginx 配置时,该站点最终会进入重定向循环。有什么我忽略的吗?

更新:我实际上不想重写 /admin 命名空间中的任何内容。下划线到破折号的重写应该只发生在/admin 命名空间中not的所有 URL。

【问题讨论】:

    标签: regex nginx


    【解决方案1】:

    Nginx location matching order 使得使用正则表达式定义的位置按照它们在配置文件中出现的顺序进行检查,并且正则表达式的搜索在第一次匹配时终止。

    有了这些知识,换位思考,我将简单地使用正则表达式为“admin”定义一个位置,上面是您从链接到的Stack Overflow Answer 获得的下划线。

    location ~ (\badmin\b) {
        # Config to process urls containing "admin"
    }
    location ~ (_) {
        # Config to process urls containing "_"
    }
    

    任何带有admin 的请求都将被第一个位置块处理,无论它是否有下划线,因为匹配的位置块出现在下划线之前。

    ** PS **

    作为 cnst 在我显示几天后发布的另一个答案,指向我发布的位置匹配顺序文档的链接也表明您也可以使用 ^~modifier 来匹配 /admin 文件夹并跳过下划线的位置块。

    我个人倾向于不使用此修饰符,而是更喜欢将基于正则表达式的位置与带注释的 cmets 结合在一起,但这当然是一种选择。

    但是,根据您的设置,您需要小心,因为以“/admin”开头但更长的请求可能与修饰符匹配并导致意外结果。

    如前所述,我更喜欢基于正则表达式的方法,因为我知道没有人会在没有清楚理解的情况下开始任意更改配置文件中的事物顺序。

    【讨论】:

    • 我同意这是一种比尝试只使用一个表达式更好的方法。
    • 我正要回答这个问题,但你的速度更快。 =) 赞成。
    • 字符串前缀匹配(在另一个答案中)比正则表达式匹配更快 —问题中没有任何迹象表明 /admin 不是 $uri 前缀字符串(这种想法是在最早的答案中自愿提出的,后来已被删除),因此,这个答案不是最佳的。此外,当有人决定在数月或数年后重新安排代码时,不得不不必要地依赖 location 指令的顺序是一种肯定的方式,从而忘记位置顺序的细微差别指令确实很重要。
    • @Dayo 在/admin 命名空间中我不想处理任何东西。我想将下划线替换为 /admin 命名空间中所有 URL not 上的连字符。通过此设置,对/admin/test_underscore 的请求似乎仍由“_”块处理。
    • 如果按照给定的方式应用配置,情况就不应该如此。
    【解决方案2】:
    ^(?!\/admin\b).*
    

    您只需要这个带有lookahead 的简单正则表达式。参见演示。

    https://regex101.com/r/uF4oY4/16

    你的正则表达式也会失败/nederland/amsterdam/car_rental,因为它有_。所以只有字符串/nederland/amsterdam/car会被考虑。

    你可以使用

    rewrite ^(?!\/admin\b)([^_]*)_(.*)$ $1-$2;
    

    【讨论】:

    • 此示例代码效率不高,因为您必须多次通过$uri 才能消除所有下划线。
    【解决方案3】:

    您没有明确提到一种或另一种方式,但看起来您可能只有一个 /admin 命名空间,它构成了 $uri 的前缀并匹配 ^/admin.*$ 正则表达式;让我根据这样的假设提供两个不冲突的配置选项。


    正如其他人所建议的,您可能希望为 /admin 使用单独的 location

    但是,与其他答案不同,我建议您通过 前缀字符串 定义它,并使用 ^~ 修饰符在成功匹配后不检查正则表达式。

    location ^~ /admin {
    }
    

    或者,甚至额外地为了更加安心和万无一失的方法,而不是使用链接答案中看似非 POSIX 正则表达式的内容(如果我对 re_format(7) on OpenBSD 的阅读是可信的),考虑一些更简单的东西,保证被大多数声称他们知道什么是 RE 的人理解,并且可以在任何地方工作,更不用说可能更有效,考虑到你已经知道它是 ^/admin.* 路径你想排除:

    location ~ ^/[^a][^d][^m][^i][^n].*_.* {
    }
    

    为了实现您的目标,您可以使用这两种解决方案中的任何一种,甚至两者都更严格和更简单。

    【讨论】:

    • 您对单个 /admin 命名空间是正确的。虽然您的解决方案看起来不错,但它不适用于路径 /amsterdam/test。显然是因为它以“a”开头。
    猜你喜欢
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多