網站根目錄的 URL 重寫
這是我在 Centos 8 上的 Apache 2.4.37 網路伺服器的配置。
文件
/etc/httpd/conf.d/mysite.conf
:<VirtualHost *:80> ServerName mysite.com DocumentRoot "/var/www/html" RewriteEngine on RewriteCond %{SERVER_NAME} =mysite.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </VirtualHost>
文件
/etc/httpd/conf.d/mysite-ssl.conf
:<IfModule mod_ssl.c> <VirtualHost *:443> ServerName mysite.com DocumentRoot "/var/www/html" Include /etc/letsencrypt/options-ssl-apache.conf SSLCertificateFile /etc/letsencrypt/live/mysite.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/mysite.com/privkey.pem ErrorDocument 403 /error403.html ErrorDocument 404 /error404.html ErrorDocument 405 /error405.html ErrorDocument 500 /error500.html RewriteEngine on # First rule block RewriteRule ^/$ /index.php [R,L] # Second rule block RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(([^/]+/)*([^/.]+))\.php[\ ?] RewriteRule \.php$ /%1/ [R=301,NC,L] RewriteRule ^(.*)/$ /$1.php [NC,L] Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains" TraceEnable off </VirtualHost> </IfModule>
第二個規則塊取自這裡並將所有 URL 重寫
https://mysite.com/anypage.php
為https://mysite.com/anypage/
,隱藏 PHP 文件副檔名並使永久連結更好看。在註意到連結中建議的解決方案有一個錯誤之後,我添加了第一個規則塊——也就是說,URL
https://mysite.com/
返回了一個未找到的文件。現在它起作用了。但是,一個小煩惱是
https://mysite.com/
重定向到https://mysite.com/index/
(因為它載入文件index.php
)。我的問題:如何更改此配置以使 URL
https://mysite.com/
保持不變?
在註意到連結中建議的解決方案存在錯誤後,我添加了第一個規則塊——即 URL https://mysite.com/ 返回了一個未找到的文件。現在它起作用了。
我認為這不是一個真正的錯誤。您從此處提取的程式碼旨在用於
.htaccess
文件中,而不是在 VirtualHost 指令中。事實證明,RewriteRule 在 .htaccess 文件中的工作方式與在 VirtualHost 指令中的工作方式不同,這就是導致一些問題的原因。讓我們看看原始程式碼:
RewriteEngine On RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(([^/]+/)*([^/.]+))\.php[\ ?] RewriteRule \.php$ /%1/ [R=301,NC,L] RewriteRule ^(.*)/$ /$1.php [NC,L]
在 VirtualHost 指令中(與 in 不同
.htaccess
),路徑的前導斜杠也與正則表達式匹配,因此,當您向 發送請求時http://mysite.com/
,規則RewriteRule ^(.*)/$ /$1.php [NC,L]
/
與正則表達式匹配^(.*)/$
。這意味著反向引用$1
將等於一個空字元串,並且生成的路徑將是/.php
您的伺服器中不存在的路徑。簡單的解決方案是將原始程式碼放在伺服器的DocumentRoot
.htaccess
中的一個文件中(即,包含所有公共文件的目錄)。但是,如果您想將 RewriteRules 保留在 VirtualHost 指令中(不推薦),您可以通過添加斜杠來稍微修改原始程式碼:
RewriteEngine On RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(([^/]+/)*([^/.]+))\.php[\ ?] RewriteRule \.php$ /%1/ [R=301,NC,L] RewriteRule ^/(.*)/$ /$1.php [NC,L]
現在向 發送請求時
http://mysite.com/
,Apache 將嘗試匹配/
但^/(.*)/$
沒有成功,因此 URL 將保持不變。另一方面,請求http://mysite.com/foo/
將與 匹配/foo/
,^/(.*)/$
將其映射到/foo.php
所需的結果。另外,請記住,當您未在 RewriteRule 中指定完整的目標 URL 時,Apache 假定它來自您伺服器的本地文件系統(而不是 DocumentRoot):
不以 http:// 或其他協議指示符開頭的重寫目標被假定為文件系統路徑。