说说.htacess的rewrite

话说这篇文章貌似受众非常的小,所以如果不知道这标题是什么意思的话。。。可以不用看了,哈哈哈。

Apache有一个重要的功能就是URL与文件可以完全无关,可以通过Rewrite规则来改变实际的URL。
而且这个功能其实非常有用,最常见的几个应用:

  • 换域名了或文件转移了,让旧地址也能访问到相应的文件。
  • 防止盗链,只允许特定网站引用文件
  • 伪静态,隐藏.php文件名,将其变成.html或直接是路径的形式
  • 自定义404等错误页面

最近因为在折腾自己的两个网站,于是除了防盗链这功能没用到以外,剩下的都实践了一遍。。。
不得不说这玩意真是一个很反人类的东西,尤其是在你不太会的时候,发现复制别人的代码也看不懂,不知道怎么改。。
想增加自己的需求那更是无限茫然,于是果然花了半天时间学习了一下。。。。

好的,下面我来简单介绍一下这玩意。。。
先说说什么是.htaccess:

.htaccess文件(或者”分布式配置文件”)提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。

概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config。

当然,其实这些设置是可以直接写在httpd.conf或vhosts里的虚拟主机配置文件中的,
但是.htaccess具有更方便控制修改,不用重启服务等优点。
它的控制范围为它所在的文件夹及其子文件夹,所以可以在子文件夹下使用来进行更小范围的控制。
缺点也是很明显的,就是性能的考虑,如果AllowOverride启用了.htaccess文件,
每访问一次Apache需要在当前目录及所有父级目录中查找.htaccess文件,
即使不存在.htaccess文件,因此,无论是否真正用到,启用.htaccess都会导致性能的下降。

当然像我这种小站其实完全不用考虑这些性能上的因素啦,于是果断的开始实践~~~~
通常这个文件是在某域名的根目录下的,如果不存在则新建一个,如果存在则直接修改。
但是修改前建议您先能看明白原来的。。。以免发生冲突。

先来说说它的基本语法:

<IfModule mod_rewrite.c>
	RewriteEngine On
	语句。。。。
</IfModule>

这里RewriteEngine On和Off可以轻松控制以下所有语句是否有效,
在调试的时候还有用,另外单独一句话可以通过在前面加#来注释掉。

Okay,下面说说常用的语句:
通常每一个重定向都是这样的:
先由一个或多个RewriteCond做为条件,满足条件的,
由RewriteRule来进行跳转。
比较常见的变量有HTTP_HOST: 域名,REQUEST_URI:域名后面那部分,REQUEST_FILENAME:文件名。
最后还有个参数,常用的有[NC]:不区分大小写,[R]:重定向,[L]:不继续执行。
条件则是使用了正则表达式,对于熟悉正则表达式的人来说,那真是变容易了,
对于不熟悉的人来说真是一头雾水,具体可以在这里补充相关知识:http://zh.wikipedia.org/zh/正则表达式
主要要注意的是开始和结束的标志,比如说如果是空的话就是^$。
更多变量参数及其代表的意义可以参考这里:http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html

下面举几个例子来说明,比如说要把所有访问domain.com的都转向www.domain.com,
当然反之也是可以的,或者用于替换域名也是可以的。
这里条件是HTTP_HOST满足domain.com,规则是转向www.domain.com,后面的内容保留。
不区分大小写,永久重定向。

RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

同样像我在上一篇BLOG中提到的,把/wp-content/uploads/的请求重定向到cdn.cnsjw.cn/uploads/下:

RewriteCond %{REQUEST_URI} ^/wp-content/uploads/ 
RewriteRule /wp-content/uploads/(.*) https://img.cnsjw.cn/$1 [R=301,L]

这里重定向就意味着告诉浏览器和搜索引擎,这个地址永远的变了,
所以重定向后会直接跳转到新的地址去。

还有就是错误页面的自定义,语法非常简单:

ErrorDocument 404 /404.html

这样就可以实现404错误的自定义页面了。

而Rewrite最常用的情况不是重定向,而是伪静态,
举的例子是eitdesign.com,这个网站之前的页面逻辑就是
eitdesign.com/home, eitdesign.com/about,等等,当时并非伪静态,而是真静态。。。
实现的方法是建立home, about等等文件夹,并在里面直接使用index文件输出当前页。

当时全站的文件结构如下:
QQ20140714-1

这个方法的问题很多,比如说每个页面都要写一次,只有这种简单的小网站才能实现。
修改起来很麻烦,而且所有的页面文件名都是index,所以开多了很混乱。。。
因为还有英文版,但是实在没有办法再新建一个/en文件夹再写一遍这些文件了。。。
于是就用了?lan=en来控制语言版本,当时是没有这个参数就是中文版,有就是英文版。
这样就导致了文件名不统一,也明显不够友好。

现在采取的方法是除了service页面以外,其它所有页面全部由index.php来处理,
内容部分从xml中读取,代码只实现功能部分。现在的文件结构是这样的:
QQ20140714-2

于是把所有的services请求做另外的rewrite,剩下的部分都直接rewrite到index.php?p=里。
这样只要在index.php里判断传过来的p参数就可以了,比如说访问http://www.eitdesign.com/home/en
实际是在访问http://www.eitdesign.com/index.php?p=home/en
然后由PHP来处理这个参数就容易得多了,用explode按照/来打散,判断/前面的部分和后面的部分,
就可以轻松的得知要访问哪个页面,哪种语言版本。

另外,要先判断不是文件名或文件夹名的话,则进行Rewrite。。否则会导致正常的文件无法访问。

RewriteCond %{REQUEST_URI} services/en/
RewriteRule . /services/en.html [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} services/
RewriteRule . /services/cn.html [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d	
RewriteRule ^(.*)$ index.php?p=$1

这样就实现了伪静态。。。

还有一个需求就是让访问www.eitdesign.com重定向到www.eitdesign.com/home/

RewriteRule ^$ /home/ [R=301,L]

这里要注意就是如果是在vhosts里设置的话,访问www.eitdesign.com的时候,
REQUEST_URI是/而不是空,只有在.htaccess中设置的时候才是空的。

总结下来其实自己也是初学者,但是呢,还是可以写得出来一些规则的。。
主要要注意的有以下几点:

  • 判断的时候设置好条件的起始和结束标记,否则就变成了包含关系。
  • 避免重复转移,以及进入死循环等问题。
  • 还有语句的顺序,满足某个条件的话就可以在结尾加[L]不再继续。
  • 注意二级域名,如果是某个目录的子目录的话,上级目录的.htaccess同样会适用于二级域名的,可能会产生错误,可以在二级域名目录的.htaccess下禁止转移。

其实自己配置服务器还挺有趣的,记得常常关注各种error log,
可以不断的改进自己的代码以及服务器的设置。

, , ,


打赏
点击这里,长按识别二维码,即可关注我们的公众号