为什么我的htaccess代码不起作用?

时间:2016-11-14 07:39:13

标签: php apache .htaccess redirect mod-rewrite

你能解释为什么我的.htaccess代码不起作用吗?无论正确的代码是什么,我都在努力更好地理解URL重写和重定向,我将非常感谢所有语法和代码的详细/详细解释。关于SO的大多数答案只是简单地说明了答案。

# Hypertext Access Directives by Govind Rai

# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Now, rewrite any request to the wrong domain to use www.
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

###############last two directives that don't work#######################

# hide .html extension govie v1
RewriteCond %{THE_REQUEST} \.html$
RewriteRule ^/[^.]+\.html$ /$1 [NC,R=301,L]

#internal redirect to the right .html file
RewriteCond %{THE_REQUEST} !\.html$
RewriteRule ^/([^.]+)$ /$1.html [L]

我想了解为什么最后两条规则不起作用。当我访问没有.html扩展名的网址时,我会收到404页面未找到错误,并且带有扩展名的网址在没有扩展名的情况下不会重写。我发布了整个文件,因为存在相互冲突的规则。

3 个答案:

答案 0 :(得分:2)

问题是这个条件:

RewriteCond %{THE_REQUEST} \.html$

该条件永远不会成功,因为%{THE_REQUEST}的示例值为GET /index.php?id=123 HTTP/1.1。它表示Apache收到的原始HTTP请求。

您可以使用这些规则来解决问题:

RewriteEngine On

## add www and turn on https in same rule

# if HOST name doesn't start with www. - OR
RewriteCond %{HTTP_HOST} !^www\. [NC,OR]
# if HTTPS is off
RewriteCond %{HTTPS} off
# *capture* hostname part after www in %1
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
# redirect with https://www.%1/... to always apply https and www
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]

## hide .html extension
# if original request is ending with .html then capture part before .html in %1
RewriteCond %{THE_REQUEST} \s/+(.+?)\.html[\s?] [NC]
# and redirect to %1 (part without .html)
RewriteRule ^ /%1 [R=302,NE,L]

# internally add .html if there a matching .html file in your web root
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+?)/?$ $1.html [L]

参考文献:

答案 1 :(得分:0)

问题很可能是一个非常简单的问题:在.htaccess样式文件中使用重写规则时,请求路径是相对的,因此坚持使用前导斜杠。这意味着您必须稍微修改规则模式:

#enable rewriting
Options -Multiviews
RewriteEngine on
RewriteMap /

#internal redirect to the right .html file
RewriteCond %{THE_REQUEST} !\.html$
RewriteCond %{THE_REQUEST} !-f
RewriteCond %{THE_REQUEST} !-d
RewriteRule ^/?([^.]+)$ /$1.html [END]

# hide .html extension govie v1
RewriteCond %{THE_REQUEST} \.html$
RewriteCond %{THE_REQUEST} -f
RewriteRule ^/?([^.]+)\.html$ /$1 [NC,R=301,END]

而不是完全删除那个前导斜杠,我个人喜欢添加问号的想法,所以使它们成为可选的。这允许在http服务器主机配置中使用相同的规则而无需修改。

我还添加了众所周知的双重规则来检查请求是否未解决物理上存在的文件或文件夹。这通常是需要的,但你显然必须自己决定。

一般提示:您应该始终更喜欢将此类规则放在http服务器真实主机配置中。这些.htaccess样式文件非常容易出错,它们很难调试,并且通常没有理由地使服务器变慢。它们仅适用于可以访问该配置的情况(读取:非常便宜的托管提供商)或者您的应用程序需要编写自己的重写规则(明显的安全噩梦)。

答案 2 :(得分:0)

${THE_REQUEST}包含浏览器发送到服务器的完整HTTP请求行(例如GET /index.html HTTP/1.1),因此它永远不会与\.html$匹配(因为它永远不会以{{1}结尾})。也许你可以试试:

.html