.htaccess - 删除 htaccess 中的特定查询字符串键/值对(但保留其他完整)

标签 .htaccess mod-rewrite iis-7 isapi-rewrite

我想建立一个 ISAPI_Rewrite 3 "RewriteRule "来处理以下永久重定向:

╔════════════════════════════════╦════════════════════════════╗
║             Input              ║           Redirect         ║
╠════════════════════════════════╬════════════════════════════╣
║ /path/?a=foo&b=bar             ║ /path/foo/bar/             ║
║ /path/?b=baz&a=qux             ║ /path/qux/baz/             ║
║ /path/?c=1&a=foo&d=2&b=bar&e=3 ║ /path/foo/bar/?c=1&d=2&e=3 ║
╚════════════════════════════════╩════════════════════════════╝

例如;
RewriteCond ${QUERY_STRING} (?:^|&)a=([\w]+)(?:&|$)
RewriteCond ${QUERY_STRING} (?:^|&)b=([\w]+)(?:&|$)
RewriteRule ^/path/$ /path/%1/%2/? [R=301]

将起作用,除了它将删除所有查询字符串对(第三个示例失败)。我似乎想不出一个优雅的解决方案来从 URL 中只删除已知的键/值对。和类似的东西......
RewriteCond ${QUERY_STRING} ^(.*)&?a=([\w]+)(.*)&?b=([\w]+)(.*)$
RewriteRule ^/path/$ /path/%2/%4/?%1%3%5 [R=301]

不完全正确(但你应该得到这个例子试图做的事情),并且很快就会变得非常困惑。

有任何想法吗?

澄清:我的第三个示例,请求 /path/?c=1&a=foo&d=2&b=bar&e=3应该重定向到 /path/foo/bar/?c=1&d=2&e=3而不是 /path/foo/bar/1/2/3/ .我可能不知道将请求哪些查询字符串对,并且其中一些可能需要保留在查询字符串中以进行客户端处理。一些示例未知查询字符串键是;
  • gclid ” - 由 Google Analytics (GA) 客户端脚本用于绑定(bind) Adwords 数据
  • utm_source” - 用于明确告诉 GA 流量来源/类型
  • 最佳答案

    我分两个阶段做到了这一点。第一个是一组规则,提取一个参数,其他参数保持不变。然后我将其扩展为两个参数。规则本身并没有那么糟糕。只是很难弄清楚。

    一个参数

    这使用 a示例的参数。有4个条件:

  • 一个只有
  • 其他
  • 其他-a
  • 其他

  • 由于问号与 & 号,最简单的做法是单独制定规则。事实证明,最后两个很容易组合成一个规则。

    (注意:我正在使用 Helicon Ape 重写,它通常与 Apache 兼容。我遇到了一个问题,即 RewriteRule 问号需要在参数之前转义,例如 \?%2 。我不知道这是否属实.)
    # a
    #  ?a=foo
    #  Starts with a=, non-ampersand to the end.
    #  Suppress querystring with trailing question mark.
    RewriteCond ${QUERY_STRING} ^a=([^&]+)$
    RewriteRule ^/path/$ /path/%1/? [NC,R=301,L]
    
    # a-other
    #  ?a=foo&b=bar, ?a=foo&b=bar&c=1
    #  Starts with a=, non-ampersand, ampersand, remaining required.
    #  Escape question mark so it doesn't include entire original querystring.
    RewriteCond ${QUERY_STRING} ^a=([^&]+)&(.+)
    RewriteRule ^/path/$ /path/%1/\?%2 [NC,R=301,L]
    
    # other-a or other-a-other
    #  ?b=baz&a=qux, ?b=baz&c=1&a=qux
    #  ?c=1&a=foo&d=2&b=bar&e=3, ?z=4&c=1&a=foo&d=2&b=bar&e=3
    #  Starts with anything, ampersand, a=, non-ampersand, remaining optional.
    #  The remaining optional lets it follow with nothing, or with ampersand and more parameters.
    #  Escape question mark so it doesn't include entire original querystring.
    RewriteCond ${QUERY_STRING} ^(.+)&a=([^&]+)(.*)$
    RewriteRule ^/path/$ /path/$2/\?%1%3 [NC,R=301,L]
    

    两个参数

    将这两个参数放在一起有点棘手,但想法是重写 a , 然后通过重写 b并重定向。要同时管理这两个部分,请重写 pathtemppath然后 temppath2 ,然后将其重写回path完成后。这确保了这些仅在两个 a 时运行。和 b存在。如果只有一个或另一个存在,那么它会跳过所有这些。 (如果您还打算只处理一个,则可以进行调整。)
    # Test cases:
    #  1) /path/?a=foo&b=bar    to    /path/foo/bar
    #  2) /path/?a=foo&b=bar&c=1     to    /path/foo/bar?c=1
    #  3) /path/?a=foo&b=bar&c=1&d=2    to    /path/foo/bar?c=1&d=2
    #  4) /path/?b=baz&a=qux    to    /path/qux/baz
    #  5) /path/?b=baz&c=1&a=qux    to    /path/qux/baz/?c=1
    #  6) /path/?c=1&b=baz&a=qux    to    /path/qux/baz/?c=1
    #  7) /path/?c=1&d=2&b=baz&a=qux    to    path/qux/baz/?c=1&d=2
    #  8) /path/?c=1&a=foo&d=2&b=bar&e=3    to    /path/foo/bar/?c=1&d=2&e=3
    #  9) /path/?z=4&c=1&a=foo&d=2&b=bar&e=3    to    /path/foo/bar/?z=4&c=1&d=2&e=3
    
    # Check for a and b (or b and a), rewrite to temp path and continue.
    RewriteCond ${QUERY_STRING} (?:^|&)(?:a|b)=.+&(?:b|a)=.+$
    RewriteRule ^/path/$ /temppath/ [NC]
    
    # a
    #  ?a=foo
    #  This case isn't needed, since we test for a and b above.
    
    # a-other
    #  1) /temppath/?a=foo&b=bar    to    /temppath2/foo/?b=bar
    #  2) /temppath/?a=foo&b=bar&c=1     to    /temppath2/foo/?b=bar&c=1
    #  3) /temppath/?a=foo&b=bar&c=1&d=2    to    /temppath2/foo/?b=bar&c=1&d=2
    #  Starts with a=, non-ampersand, ampersand, remaining required.
    RewriteCond ${QUERY_STRING} ^a=([^&]+)&(.+)$
    RewriteRule ^/temppath/$ /temppath2/%1/\?%2 [NC]
    
    # other-a or other-a-other
    #  4) /temppath/?b=baz&a=qux    to    /temppath2/qux/?b=baz
    #  5) /temppath/?b=baz&c=1&a=qux    to    /temppath2/qux/?b=baz&c=1
    #  6) /temppath/?c=1&b=baz&a=qux    to    /temppath2/qux/?c=1&b=baz
    #  7) /temppath/?c=1&d=2&b=baz&a=qux    to    /temppath2/qux/?c=1&d=2&b=baz
    #  8) /temppath/?c=1&a=foo&d=2&b=bar&e=3    to    /temppath2/foo/?c=1&d=2&b=bar&e=3
    #  9) /temppath/?z=4&c=1&a=foo&d=2&b=bar&e=3    to    /temppath2/foo/?z=4&c=1&d=2&b=bar&e=3
    #  Starts with anything, ampersand, a=, non-ampersand, remaining optional.
    #  The remaining optional lets it follow with nothing, or with ampersand and more parameters.
    #  Escape question mark so it doesn't include entire original querystring.
    RewriteCond ${QUERY_STRING} ^(.+)&a=([^&]+)(.*)$
    RewriteRule ^/temppath/$ /temppath2/%2/\?%1%3 [NC]
    
    # b
    #  1) /temppath2/foo/?b=bar    to    /path/foo/bar
    #  4) /temppath2/qux/?b=baz    to    /path/qux/baz
    #  Starts with b=, non-ampersand to the end.
    #  Capture and use path after temppath2, since it has the a folder from above.
    RewriteCond ${QUERY_STRING} ^b=([^&]+)$
    RewriteRule ^/temppath2/(.*)/$ /path/$1/%1/? [NC,R=301,L]
    
    # b-other
    #  2) /temppath2/foo/?b=bar&c=1    to    /path/foo/bar?c=1
    #  3) /temppath2/foo/?b=bar&c=1&d=2    to    /path/foo/bar?c=1&d=2
    #  5) /temppath2/qux/?b=baz&c=1    to    /path/qux/baz/?c=1
    #  Starts with b=, non-ampersand, ampersand, remaining required.
    #  Capture and use path after temppath2, since it has the a folder from above.
    #  Escape question mark so it doesn't include entire original querystring.
    RewriteCond ${QUERY_STRING} ^b=([^&]+)&(.+)$
    RewriteRule ^/temppath2/(.*)/$ /path/$1/%1/\?%2 [NC,R=301,L]
    
    # other-b or other-b-other
    #  6) /temppath2/qux/?c=1&b=baz    to    /path/qux/baz/?c=1
    #  7) /temppath2/qux/?c=1&d=2&b=baz    to    /path/qux/baz/?c=1&d=2
    #  8) /temppath2/foo/?c=1&d=2&b=bar&e=3    to    /path/foo/bar/?c=1&d=2&e=3
    #  9) /temppath2/foo/?z=4&c=1&d=2&b=bar&e=3    to    /path/foo/bar/?z=4&c=1&d=2&e=3
    #  Starts with anything, ampersand, b=, non-ampersand, remaining optional.
    #  The remaining optional lets it follow with nothing, or with ampersand and more parameters.
    #  Capture and use path after temppath2, since it has the a folder from above.
    #  Escape question mark so it doesn't include entire original querystring.
    RewriteCond ${QUERY_STRING} ^(.+)&b=([^&]+)(.*)$
    RewriteRule ^/temppath2/(.*)/$ /path/$1/%2/\?%1%3 [NC,R=301,L]
    

    在代码中可能更容易......

    关于.htaccess - 删除 htaccess 中的特定查询字符串键/值对(但保留其他完整),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16658881/

    相关文章:

    php - 3 关于 .htaccess 的问题

    asp.net-mvc - ASP.NET MVC 中无法访问服务器变量

    asp.net - IIS7 和 IE8 - 页面在相同版本的 IE8 上呈现不同?

    .htaccess - HTTPS URL 中的 Codeigniter Index.php

    javascript - 启用js重定向到apache服务器的私有(private)文件夹

    regex - RewriteCond 无法对 HTTP_HOST 强制使用 https

    php - 文件夹内的 CodeIgniter、NGINX 不工作

    css - 允许重写引擎中的样式表

    c# - 应用程序因 stackoverflow 而崩溃

    php - 如何记录不正确的条目 (php .htaccess)