为了账号安全,请及时绑定邮箱和手机立即绑定

mod_rewrite的隐藏功能

/ 猿问

mod_rewrite的隐藏功能

缥缈止盈 2019-09-18 10:41:15

mod_rewrite最近似乎有相当数量的线程浮出水面,对它的某些方面如何工作有点混淆。结果我编写了一些关于常见功能的注释,也许还有一些烦人的细微差别。

您遇到过哪些其他功能/常见问题mod_rewrite


查看完整描述

3 回答

?
慕容3067478

在哪里放置mod_rewrite规则

mod_rewrite规则可以放在httpd.conf文件中,也可以放在.htaccess文件中。如果您有权访问httpd.conf,则在此处放置规则将提供性能优势(因为规则处理一次,而不是每次.htaccess调用文件时)。


记录mod_rewrite请求

可以从httpd.conf文件中启用日志记录(包括<Virtual Host>):


# logs can't be enabled from .htaccess

# loglevel > 2 is really spammy!

RewriteLog /path/to/rewrite.log

RewriteLogLevel 2

常见用例

将所有请求汇集到一个点:


RewriteEngine on

# ignore existing files

RewriteCond %{REQUEST_FILENAME} !-f   

# ignore existing directories

RewriteCond %{REQUEST_FILENAME} !-d   

# map requests to index.php and append as a query string

RewriteRule ^(.*)$ index.php?query=$1 

自Apache 2.2.16起,您也可以使用FallbackResource。


处理301/302重定向:


RewriteEngine on

# 302 Temporary Redirect (302 is the default, but can be specified for clarity)

RewriteRule ^oldpage\.html$ /newpage.html [R=302]  

# 301 Permanent Redirect

RewriteRule ^oldpage2\.html$ /newpage.html [R=301] 

注意:外部重定向是隐含的302重定向:


# this rule:

RewriteRule ^somepage\.html$ http://google.com

# is equivalent to:

RewriteRule ^somepage\.html$ http://google.com [R]

# and:

RewriteRule ^somepage\.html$ http://google.com [R=302]

强制SSL


RewriteEngine on

RewriteCond %{HTTPS} off

RewriteRule ^(.*)$ https://example.com/$1 [R,L]

常用标志:


[R]或[redirect]- 强制重定向(默认为302临时重定向)

[R=301]或[redirect=301]- 强制执行301永久重定向

[L]或[last]- 停止重写过程(见常见陷阱中的注释)

[NC]或[nocase]- 指定匹配应不区分大小写


使用长形式的标志通常更具可读性,并且可以帮助其他人以后阅读您的代码。


您可以使用逗号分隔多个标志:


RewriteRule ^olddir(.*)$ /newdir$1 [L,NC]

常见的陷阱

混合mod_alias风格重定向mod_rewrite


# Bad

Redirect 302 /somepage.html http://example.com/otherpage.html

RewriteEngine on

RewriteRule ^(.*)$ index.php?query=$1


# Good (use mod_rewrite for both)

RewriteEngine on

# 302 redirect and stop processing

RewriteRule ^somepage.html$ /otherpage.html [R=302,L] 

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

# handle other redirects

RewriteRule ^(.*)$ index.php?query=$1                 

注意:您可以混合mod_alias使用mod_rewrite,但它涉及的工作不仅仅是处理上面的基本重定向。


上下文影响语法


在.htaccess文件中,RewriteRule模式中不使用前导斜杠:


# given: GET /directory/file.html


# .htaccess

# result: /newdirectory/file.html

RewriteRule ^directory(.*)$ /newdirectory$1


# .htaccess

# result: no match!

RewriteRule ^/directory(.*)$ /newdirectory$1


# httpd.conf

# result: /newdirectory/file.html

RewriteRule ^/directory(.*)$ /newdirectory$1


# Putting a "?" after the slash will allow it to work in both contexts:

RewriteRule ^/?directory(.*)$ /newdirectory$1

[L]不是最后一个!(有时)


该[L]标志停止处理该通过规则集的任何进一步重写规则。但是,如果在该传递中修改了URL并且您在.htaccess上下文或<Directory>部分中,那么您修改的请求将再次通过URL解析引擎传回。在下一次传球中,这次可能会匹配不同的规则。如果您不理解这一点,通常看起来您的[L]旗帜没有效果。


# processing does not stop here

RewriteRule ^dirA$ /dirB [L] 

# /dirC will be the final result

RewriteRule ^dirB$ /dirC     

我们的重写日志显示规则运行两次,URL更新两次:


rewrite 'dirA' -> '/dirB'

internal redirect with /dirB [INTERNAL REDIRECT]

rewrite 'dirB' -> '/dirC'

解决这个问题的最好方法是使用[END]标志(请参阅Apache文档)而不是[L]标志,如果您真的想要停止所有进一步处理规则(以及后续传递)。但是,该[END]标志仅适用于Apache v2.3.9 +,因此如果您使用的是v2.2或更低版本,则只会使用该[L]标志。


对于早期版本,您必须依赖RewriteCond语句来防止在URL解析引擎的后续传递中匹配规则。


# Only process the following RewriteRule if on the first pass

RewriteCond %{ENV:REDIRECT_STATUS} ^$

RewriteRule ...

或者您必须确保您的RewriteRule位于上下文(即httpd.conf)中,不会导致您的请求被重新解析。


查看完整回答
反对 回复 2019-09-18
?
慕哥9229398

与RewriteBase的交易:


您几乎总是需要设置RewriteBase。如果不这样做,apache会猜测您的base是目录的物理磁盘路径。所以从这开始:


RewriteBase /


查看完整回答
反对 回复 2019-09-18
  • 3 回答
  • 0 关注
  • 161 浏览
我要回答
慕课专栏
更多

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信