如何使用 mod_rewrite 搜索和替换 GET 参数
How to search and replace GET parameters with mod_rewrite
我尝试在 httpd.conf 文件中的 apache 网络服务器配置上写一个重写规则,它应该将每个包含 &foo= 的 GET 参数键替换为 &poo= 但不应该更改任何其他 GET 参数。
例如:
https://test.com/imb/rs/search?test=abc&foo=123&test2=def&foo=456
应改为:
https://test.com/imb/rs/search?test=abc&poo=123&test2=def&poo=456
我试过:
RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ ?%1?&poo=%2 [NC]
但它只是将最后一次出现的 foo 更改为 poo。
我的 httpd.conf 文件结构如下:
<Directory ~ "^/imb/rs/*">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ ?%1&poo=%2 [NC]
</Directory>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ ?%1&poo=%2 [NC]
</IfModule>
写/imb/rs/部分是因为url从https://test.com/imb/rs/开始,然后继续。我认为这符合我的情况。
有人知道我该如何解决这个问题吗?
我发现此解决方案仅适用于 1 次出现,不适用于多次出现。
这个只需要第一次出现:
RewriteCond %{QUERY_STRING} (.*?)foo(.*) [NC]
RewriteRule ^ %{REQUEST_URI}?%1poo%2 [NC]
这个只需要最后一次出现:
RewriteCond %{QUERY_STRING} (.*)foo(.*) [NC]
RewriteRule ^ %{REQUEST_URI}?%1poo%2 [NC]
但我找不到替换所有这些的方法。
<Directory ~ "^/imb/rs/*">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ ?%1&poo=%2 [NC]
</Directory>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ ?%1&poo=%2 [NC]
</IfModule>
这里有一些问题。 <Directory>
容器不会匹配请求,因此不会处理此容器内的 mod_rewrite 指令。仅处理 <Directory>
容器外的 mod_rewrite 指令,但这只会替换查询字符串中 &foo=
的 last 实例(因为正则表达式是 greedy 并且重写引擎只在 vHost/server 上下文中进行一次传递。
<Directory ~ "^/imb/rs/*">
您正在混合使用正则表达式和通配符语法。但是,这应该是绝对文件系统路径,而不是 URL-path,因为这看起来是(“url 以 https://test.com/imb/rs/
”开头)。但是无论如何,您不需要在此处使用 <Directory>
指令的正则表达式版本。我假设 /imb/rs
是物理目录而不仅仅是虚拟目录 URL-path?
AllowOverride All
您正在明确启用 .htaccess
覆盖。如果您在该目录中确实有一个包含 mod_rewrite 指令的 .htaccess
文件,那么这将完全覆盖服务器配置中的 <Directory>
容器。您可能应该完全禁用 .htaccess
覆盖。
Order allow,deny
Allow from all
这些是 Apache 2.2 指令,以前在 Apache 2.4 上已弃用(我假设您正在使用它)。您应该使用等效的 Require all granted
来代替。 (但您确实需要确保自始至终都在使用 Apache 2.4 指令 - 不要将两者混用。)
Options Indexes FollowSymLinks
旁白:您是否有意允许 mod_autoindex 生成您内容的目录列表?通常,这应该被禁用(即从该规则中删除 Indexes
)。
请尝试以下方法:
<Directory "/absolute/file/path/to/imb/rs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
RewriteEngine On
RewriteCond %{QUERY_STRING} (.*)&foo=(.*)
RewriteRule (.*) ?%1&poo=%2 [L]
</Directory>
并从 <Directory>
容器外部删除规则。
所以,你一开始的规则基本没问题。这里不需要 start-of-string 和 end-of-string 锚点,因为正则表达式是 greedy。 NC
标志不是必需的。 L
标志不是严格要求的,但如果您稍后添加更多规则,则需要。
我尝试在 httpd.conf 文件中的 apache 网络服务器配置上写一个重写规则,它应该将每个包含 &foo= 的 GET 参数键替换为 &poo= 但不应该更改任何其他 GET 参数。 例如:
https://test.com/imb/rs/search?test=abc&foo=123&test2=def&foo=456
应改为:
https://test.com/imb/rs/search?test=abc&poo=123&test2=def&poo=456
我试过:
RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ ?%1?&poo=%2 [NC]
但它只是将最后一次出现的 foo 更改为 poo。
我的 httpd.conf 文件结构如下:
<Directory ~ "^/imb/rs/*">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ ?%1&poo=%2 [NC]
</Directory>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$
RewriteRule ^(.*)$ ?%1&poo=%2 [NC]
</IfModule>
写/imb/rs/部分是因为url从https://test.com/imb/rs/开始,然后继续。我认为这符合我的情况。
有人知道我该如何解决这个问题吗?
我发现此解决方案仅适用于 1 次出现,不适用于多次出现。
这个只需要第一次出现:
RewriteCond %{QUERY_STRING} (.*?)foo(.*) [NC]
RewriteRule ^ %{REQUEST_URI}?%1poo%2 [NC]
这个只需要最后一次出现:
RewriteCond %{QUERY_STRING} (.*)foo(.*) [NC]
RewriteRule ^ %{REQUEST_URI}?%1poo%2 [NC]
但我找不到替换所有这些的方法。
<Directory ~ "^/imb/rs/*"> Options Indexes FollowSymLinks AllowOverride All Order allow,deny Allow from all RewriteEngine on RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$ RewriteRule ^(.*)$ ?%1&poo=%2 [NC] </Directory> <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{QUERY_STRING} ^(.*)&foo=(.*)$ RewriteRule ^(.*)$ ?%1&poo=%2 [NC] </IfModule>
这里有一些问题。 <Directory>
容器不会匹配请求,因此不会处理此容器内的 mod_rewrite 指令。仅处理 <Directory>
容器外的 mod_rewrite 指令,但这只会替换查询字符串中 &foo=
的 last 实例(因为正则表达式是 greedy 并且重写引擎只在 vHost/server 上下文中进行一次传递。
<Directory ~ "^/imb/rs/*">
您正在混合使用正则表达式和通配符语法。但是,这应该是绝对文件系统路径,而不是 URL-path,因为这看起来是(“url 以 https://test.com/imb/rs/
”开头)。但是无论如何,您不需要在此处使用 <Directory>
指令的正则表达式版本。我假设 /imb/rs
是物理目录而不仅仅是虚拟目录 URL-path?
AllowOverride All
您正在明确启用 .htaccess
覆盖。如果您在该目录中确实有一个包含 mod_rewrite 指令的 .htaccess
文件,那么这将完全覆盖服务器配置中的 <Directory>
容器。您可能应该完全禁用 .htaccess
覆盖。
Order allow,deny Allow from all
这些是 Apache 2.2 指令,以前在 Apache 2.4 上已弃用(我假设您正在使用它)。您应该使用等效的 Require all granted
来代替。 (但您确实需要确保自始至终都在使用 Apache 2.4 指令 - 不要将两者混用。)
Options Indexes FollowSymLinks
旁白:您是否有意允许 mod_autoindex 生成您内容的目录列表?通常,这应该被禁用(即从该规则中删除 Indexes
)。
请尝试以下方法:
<Directory "/absolute/file/path/to/imb/rs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
RewriteEngine On
RewriteCond %{QUERY_STRING} (.*)&foo=(.*)
RewriteRule (.*) ?%1&poo=%2 [L]
</Directory>
并从 <Directory>
容器外部删除规则。
所以,你一开始的规则基本没问题。这里不需要 start-of-string 和 end-of-string 锚点,因为正则表达式是 greedy。 NC
标志不是必需的。 L
标志不是严格要求的,但如果您稍后添加更多规则,则需要。