AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1140610
Accepted
Michel Zúñiga
Michel Zúñiga
Asked: 2023-08-03 23:06:29 +0800 CST2023-08-03 23:06:29 +0800 CST 2023-08-03 23:06:29 +0800 CST

htaccess 在特定 url 上使用特殊字符进行重定向不起作用

  • 772

我需要一些帮助来创建重定向,我正在尝试将所有内容替换为-,+但两者都是特殊字符,并且仅当 URL 包含 时才执行此操作?s=。

这是一个例子

example.com/?s=i-need-to-rewrite-this-url
example.com/?s=i+need+to+rewrite+this+url

这就是我所拥有的,我已经尝试使用()或""但没有工作

RewriteEngine on
RewriteRule ^?s=(.*)\-(.*)$ ?s=$1\+$2 [L,R=301]

我很感激任何帮助。谢谢。

.htaccess
  • 1 1 个回答
  • 21 Views

1 个回答

  • Voted
  1. Best Answer
    MrWhite
    2023-08-04T01:11:21+08:002023-08-04T01:11:21+08:00

    我正在尝试将所有-内容替换为+,但两者都是特殊字符

    这些角色没有什么特别“特别”的地方。至少,不是在将要使用它们的上下文中。(-连字符) 在正则表达式字符类中使用时是范围说明符,否则它只是一个连字符,可以安全地在 URL 的查询字符串部分中使用未编码的内容(我们不需要在正则表达式字符类中使用它)。( +plus) 是正则表达式量词,但我们不需要在正则表达式中使用它,只需在替换字符串中使用它(RewriteRule指令的第二个参数,不是正则表达式)。是+一个编码空间当在 URL 的查询字符串部分中使用时 - 我猜您已经意识到这一点,这就是为什么您需要重定向请求(尽管由于这是 URL 参数值的一部分,所以也很好奇为什么不能在应用程序)。

    然而,值得注意的一件事是,由于+是 URL 编码空间,我们确实需要在指令上使用NE( noescape) 标志RewriteRule来防止 mod_rewrite在重定向响应中对+as %2B(文字)进行 URL 编码。(这同样适用于我们可能从- 此服务器变量未进行%解码的+任何其他%编码字符。)QUERY_STRING

    RewriteRule ^?s=(.*)\-(.*)$ ?s=$1\+$2 [L,R=301]
    

    模式(第一个参数)仅与 URL 路径匹配,而不与查询字符串匹配RewriteRule 。因此,RewriteRule单独的指令永远不会匹配查询字符串。顺便说一句,?是一个特殊的正则表达式字符(前面的标记的 0 或 1 个量词)并且^(前面的标记)是不可量化的,所以我会惊讶这是否会编译(导致 500 内部服务器错误)。正则表达式中的文字?需要进行反斜杠转义。

    如上所述,NE这里需要该标志。并且不需要在替换字符串+中进行反斜杠转义,因为它在这里没有特殊含义(它不是正则表达式)。另外,由于相对替换字符串(即。),除非您定义了该字符串,否则这将导致格式错误的重定向。?s=$1\+$2RewriteBase

    要匹配查询字符串,您需要一个附加条件(RewriteCond指令)并匹配QUERY_STRING服务器变量。因此,作为第一次尝试,您可以执行以下操作:

    # First attempt (inefficient when multiple "-" are present)
    RewriteCond %{QUERY_STRING} ^s=([^&]*)-([^&]*)
    RewriteRule ^$ /?s=%1+%2 [NE,R=301,L]
    

    请注意,%1和%2反向引用(与 等相对)包含从前面的CondPattern(指令)$1捕获的值,而不是模式(在本例中仅匹配空字符串)。RewriteCondRewriteRule

    (注意:您应该始终首先使用 302 - 临时 - 重定向进行测试,以避免潜在的缓存问题,并确保在测试之前清除所有中间缓存。)

    我假设s是唯一的URL 参数。根据上述规则,后面的任何其他 URL 参数都将被丢弃。

    然而,上面的方法非常低效,因为它会为每个 实例触发外部重定向-。因此,您的示例/?s=i-need-to-rewrite-this-url将触发 5 个重定向。

    解决方案

    您应该在内部递归地替换除一个之外的所有内容,而不是上面的内容,-并且仅在替换所有内容后才触发外部重定向(并替换最后一个-)-。为此,我们需要额外重写来执行内部替换。例如:

    # Internally replace all but the last "-" with "+" in the URL param
    RewriteCond %{QUERY_STRING} ^s=([^&]*-[^&]*){2}
    RewriteCond %{QUERY_STRING} ^s=([^&]*)-([^&]*)
    RewriteRule ^$ ?s=%1+%2 [N=20]
    
    # Replace the last "-" and redirect
    RewriteCond %{QUERY_STRING} ^s=([^&-]*)-([^&-]*)
    RewriteRule ^$ /?s=%1+%2 [NE,R=301,L]
    

    检查正则表达式的第一个条件^s=([^&]*-[^&]*){2}只是确定sURL 参数的值中至少有 2 个连字符。(否则该规则将被跳过并直接进入第二个/重定向规则。)第二个条件然后捕获最后一个周围的查询字符串的相关部分-,然后在下面的中使用它们RewriteRule。

    该N标志使重写引擎立即重新启动。它20设置了迭代次数的限制(Apache 2.4+) - 所以我假设不超过 20+1 个连字符(最后一个连字符在第二个/重定向规则中被替换)。

    由于我们知道处理第二条规则时 URL 参数中最多仅保留 1 个连字符,因此我将连字符添加到正则表达式字符类中作为优化,以避免不必要的回溯。


    未来

    replaceApache 表达式中有一个函数,(顾名思义)允许您搜索/替换字符串中的字符,但我认为最新的公共版本中尚未提供该函数。但这可能允许您在单个规则中执行类似以下操作:

    RewriteCond %{QUERY_STRING} ^s=[^&]*-
    RewriteCond expr "replace(%{QUERY_STRING},'-','+') =~ /^s=([^&]+)/"
    RewriteRule ^$ /?s=%1 [NE,R=301,L]
    
    • 1

相关问题

  • apache重写以将文件夹分配给域

  • Apache conf 或 .htaccess 规则将 404 重定向到特定文件类型的另一个位置

  • 如何让 Apache2 重定向到子目录

  • .htaccess - 删除所有 cookie

  • 我的 .htaccess 文件是什么意思?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve