This is the configuration of my Apache 2.4.37 webserver on Centos 8.
File /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>
File /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>
The second rule block is taken from here and rewrites all URLs https://mysite.com/anypage.php
to https://mysite.com/anypage/
, hiding PHP file extensions and making permalinks nicer to see.
I've added the first rule block after noticing that the solution suggested in the link had a bug -- that is, URL https://mysite.com/
returned a File not Found. Now it works.
However, a minor annoyance is that https://mysite.com/
redirects to https://mysite.com/index/
(since it loads the file index.php
).
My question: How can this configuration be changed so that the URL https://mysite.com/
stays the same?
答案1
在注意到链接中建议的解决方案有一个错误(即 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 指令中(与 中不同.htaccess
),路径的前导斜杠也会与正则表达式匹配,因此,当您向 发送请求时http://mysite.com/
,规则
RewriteRule ^(.*)/$ /$1.php [NC,L]
/
与正则表达式匹配^(.*)/$
。这意味着反向引用$1
将等于空字符串,并且生成的路径将是/.php
您的服务器中不存在的路径。
简单的解决方案是将原始代码放在一个.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:// 或其他协议指示符开头的重写目标被假定为文件系统路径。
答案2
我通过更改主页的所有内部链接解决了我的问题
https://mysite.com/index.php
到
https://mysite.com/