嵌套 URL 的 Apache2 .htaccess 重写规则不起作用
Apache2 .htaccess rewrite rule for nested URLs doesn't work
我有一个简单的 php 应用程序,其导航基于 domain/foo/bar
嵌套的 urls。
例如,我的主页 index.php
和 about
导航 link 应该导航到 domain/en/about
,其中 en
和 about
必须转移到 url 参数,如 index.php?url=...
.
但是当我点击 about
时,我 domain/en/about
并且
404 not found 相反。
我已将 apache2 虚拟域配置配置为:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
<Directory /var/www/html/domain>
Options -Indexes +FollowSymLinks -MultiViews
AllowOverride All
Require all granted
</Directory>
DocumentRoot /var/www/domain/
ServerName domain.local
ServerAlias www.domain.local
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
和.htaccess
文件为:
order deny,allow
RewriteEngine On
RewriteBase /
RewriteRule .* index.php?url=[=11=] [QSA,L]
mod_rewrite
for apache2 已经启用。
不知道我错过了什么。
感谢任何帮助!
提前致谢!
您需要在要捕获的内容周围加上括号。 Back-references 索引以“1”开头:
RewriteRule (.*) index.php?url= [L,QSA]
<Directory /var/www/html/domain>
:
DocumentRoot /var/www/domain/
您的 <Directory>
部分和 DocumentRoot
指令指向不同的位置,因此无论您将 .htaccess
文件放在哪里,它都不会按预期工作。
然而...
RewriteRule .* index.php?url=[=11=] [QSA,L]
这条规则并不严格正确,因为它最终会在重写引擎第二次通过时重写自己。如果不是 QSA
标志,原始的 url
参数值(包含最初请求的 URL-path)将会丢失。上面的代码最终将 /en/about
的请求重写为 index.php?url=index.php&url=en/about
。幸运的是,您的 PHP 脚本仍将 $_GET['url']
读作 en/about
。但是您可以检查 $_SERVER['QUERY_STRING']
.
中的完整(错误)查询字符串
(而且,如果您只是在 替换 字符串前加上斜杠,即 URL-path,您将得到无穷无尽的 rewrite-loop(500 内部服务器错误)。但这也可能是由于稍后添加其他规则造成的。)
您应该防止对 index.php
本身的请求被重写,您可以通过添加额外的规则来做到这一点。例如:
RewriteRule ^index\.php$ - [L]
RewriteRule .* index.php?url=[=12=] [QSA,L]
但是,这仍然会重写您的静态资产(假设您正在链接到内部图像、CSS 和 JS 文件?)。因此,您通常需要使用额外的 条件 来防止这种情况,如果请求已经映射到静态文件,则阻止处理规则。
例如:
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php?url=[=13=] [QSA,L]
CondPattern -f
检查 TestString 是否映射到文件。 !
前缀否定了这一点。因此,只有当请求 not 映射到文件时,条件才会成功。
我有一个简单的 php 应用程序,其导航基于 domain/foo/bar
嵌套的 urls。
例如,我的主页 index.php
和 about
导航 link 应该导航到 domain/en/about
,其中 en
和 about
必须转移到 url 参数,如 index.php?url=...
.
但是当我点击 about
时,我 domain/en/about
并且
404 not found 相反。
我已将 apache2 虚拟域配置配置为:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
<Directory /var/www/html/domain>
Options -Indexes +FollowSymLinks -MultiViews
AllowOverride All
Require all granted
</Directory>
DocumentRoot /var/www/domain/
ServerName domain.local
ServerAlias www.domain.local
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
和.htaccess
文件为:
order deny,allow
RewriteEngine On
RewriteBase /
RewriteRule .* index.php?url=[=11=] [QSA,L]
mod_rewrite
for apache2 已经启用。
不知道我错过了什么。
感谢任何帮助! 提前致谢!
您需要在要捕获的内容周围加上括号。 Back-references 索引以“1”开头:
RewriteRule (.*) index.php?url= [L,QSA]
<Directory /var/www/html/domain> : DocumentRoot /var/www/domain/
您的 <Directory>
部分和 DocumentRoot
指令指向不同的位置,因此无论您将 .htaccess
文件放在哪里,它都不会按预期工作。
然而...
RewriteRule .* index.php?url=[=11=] [QSA,L]
这条规则并不严格正确,因为它最终会在重写引擎第二次通过时重写自己。如果不是 QSA
标志,原始的 url
参数值(包含最初请求的 URL-path)将会丢失。上面的代码最终将 /en/about
的请求重写为 index.php?url=index.php&url=en/about
。幸运的是,您的 PHP 脚本仍将 $_GET['url']
读作 en/about
。但是您可以检查 $_SERVER['QUERY_STRING']
.
(而且,如果您只是在 替换 字符串前加上斜杠,即 URL-path,您将得到无穷无尽的 rewrite-loop(500 内部服务器错误)。但这也可能是由于稍后添加其他规则造成的。)
您应该防止对 index.php
本身的请求被重写,您可以通过添加额外的规则来做到这一点。例如:
RewriteRule ^index\.php$ - [L]
RewriteRule .* index.php?url=[=12=] [QSA,L]
但是,这仍然会重写您的静态资产(假设您正在链接到内部图像、CSS 和 JS 文件?)。因此,您通常需要使用额外的 条件 来防止这种情况,如果请求已经映射到静态文件,则阻止处理规则。
例如:
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php?url=[=13=] [QSA,L]
CondPattern -f
检查 TestString 是否映射到文件。 !
前缀否定了这一点。因此,只有当请求 not 映射到文件时,条件才会成功。