一、rewrite定义
rewrite 对称 url rewrite,即 url 重写,就是把传入 web 的请求重定向到其他 url 的过程。url rewrite 最常见的应用是 url 伪静态化,是将动态页面显示为静态页面方式的一种技术。比如 http://www.123.com/news/index.asp?id=123 使用 url rewrite 转换后可以显示为 http://www.123.com/news/123.html
对于追求完美主义的网站设计师,就算是网页的地址也希望看起来尽量简洁明快。形如http://www.123.com/news/index.asp?id=123 的网页地址,自然是毫无美感可言,而用urlrewrite 技术,你可以轻松把它显示为 http://www.123.com/news/123.html。
理论上,搜索引擎更喜欢静态页面形式的网页,搜索引擎对静态页面的评分一般要高于动态页面。所以,urlrewrite 可以让我们网站的网页更容易被搜索引擎所收录。
从安全角度上讲,如果在 url 中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的 url 地址可以给我们带来更高的安全性。
二、rewrite 语法
1.nginx rewrite 为地址改写,在改写之前需先匹配。
匹配(针对什么内容进行改写),分为路径匹配和主机匹配。路径匹配通常用 location 字段去定义,主机匹配部分会用到 if
~ 为区分大小写匹配
~* 为不区分大小写匹配
!~和!~*分别为区分大小写不匹配及不区分大小写不匹配
-f 和!-f 用来判断是否存在文件
-d 和!-d 用来判断是否存在目录
-e 和!-e 用来判断是否存在文件或目录
-x 和!-x 用来判断文件是否可执行
在匹配过程中可以引用一些 nginx 的全局变量
$args, 请求中的参数;
$document_root, 针对当前请求的根路径设置值;
$http_host, 请求信息中的"Host",如果请求中没有 Host 行,则等于设置的服务器名; (比较常用)
$limit_rate, 对连接速率的限制;
$request_method, 请求的方法,比如"GET"、"POST"等;
$remote_addr, 客户端地址;
$remote_port, 客户端端口号;
$remote_user, 客户端用户名,认证用;
$request_filename, 当前请求的文件路径名
$query_string, 与$args 相同;
$scheme, 所用的协议,比如 http 或者是 https
$server_protocol, 请求的协议版本,"HTTP/1.0"或"HTTP/1.1";
$server_addr, 服务器地址,如果没有用 listen 指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$server_name, 请求到达的服务器名;
$document_uri 与$uri 一样,URI 地址;
$server_port, 请求到达的服务器端口号;
改写
这时会调用到关键字 rewrite
用法: rewrite 旧地址(客户输入的url地址) 新地址(文件实际存放路径) 标记位
标记位:last 会做二次匹配
break 不会做二次匹配
perment 对于用户来说,可以看到我们改写的域名(比较常用)
redirect 浏览器地址会显示跳转后的 URL 地址
备注:last 和 break 我们改写完地址后,用户是看不到新地址的,而 perment 和 redirect 我们改写完地址后,用户是可以看到新地址的
三、实验
1、进入 www.abc.com 的网页文件根目录,该目录下创建 news 测试目录,在 news 下创建一些测试文件,测试文件中包含index.html
mkdir /usr/share/nginx/abc.com/news
echo building > /usr/share/nginx/abc.com/news/index.html
touch new1.html new2.html new3.html (new123为测试文件)
编写 rewrite,因为是匹配路径,所以使用 location 即可,如下所示,如果$path 中匹配到/news/,则将从/news/开始后边匹配任意字符的地址重写为/news/index.html,标记位使用 break,停止匹配,如果使用 last 则出现死循环,因为改写完成的地址中仍然包含/news,使用 last 会进行二次改写。
vim /etc/nginx/conf.d/www.joy.com.conf
server {
listen 80;
server_name www.abc.com;
root /usr/share/nginx/abc.com;
index index.html index.htm;
location ~* /news/ {
rewrite ^/news/.* /news/index.html break;
}
重启服务: systemctl restart nginx.service
2、用户在访问 www.abc.com 网站时访问地址如果为/uplook/11-22-33.html 重写后真实地址为/uplook/11/22/33.html
mkdir -p /usr/share/nginx/uplook/11/22
echo aaa > /usr/share/nginx/uplook/11/22/33.html
编写 rewrite,location 匹配 $path,改写中使用到正则表达式,旧地址中 ^ 表示以某个字符串开始, [ ] 表示匹配字符组的任一字符, + 表示匹配前一字符 1 次及 1 次以上,\ 表示转义, ( ) 用于字符串保存,$表示以某个字符串结尾,新地址中 \$ 用于引用保存的内存,\$1 表示第一个被保存的字符串,依次类推。
vim /etc/nginx/conf.d/www.abc.com.conf
server {
listen 80;
server_name www.abc.com;
root /usr/share/nginx/abc.com;
index index.html index.htm;
location ~* /home {
rewrite ^/home/([0-9]+)-([0-9]+)-([0-9]+)\.html$ /home/$1/$2/$3.html last;
}
}
重启服务:systemctl restart nginx.service
测试:www.abc.com/home/11-22-33.html
3、用户在访问 tom.abc.com 网站时访问的实际位置为/usr/share/nginx/abc.com/tom 目录下的文件
mkdir /usr/share/nginx/abc.com/tom
echo tom > /usr/share/nginx/abc.com/tom
vim /etc/nginx/conf.d/www.abc.com.conf
server {
listen 80;
server_name ~.*.abc.com;
root /usr/share/nginx/abc.com;
index index.html index.htm;
if ( $http_host ~* ^www\.joy\.com$ ) {
break;
}
如果用户访问的是 www.joy.com,则不做 rewrite
if ( $http_host ~* ^(.*)\.joy\.com$ ) {
set $domain $1;
rewrite /.* /$domain/index.html break;
}
}
重启服务:systemctl restart nginx.service
测试:tom.abc.com
4、用户在访问www.abc.com/pictures/123.png 网站访问的实际位置为/usr/share/nginx/abc.com/pictures/png/123.png
mkdir usr/share/nginx/abc.com/pictures/png -p
vim /etc/nginx/conf.d/www.abc.com.conf
server {
listen 80;
server_name www.abc.com;
root /usr/share/nginx/abc.com;
index index.html index.htm;
location ~* /pictures {
rewrite ^/pictures/(.*)\.(.*)$ /pictuires/$2/$1.$2 break;
}
}
重启服务:systemctl restart nginx.service
测试:www.abc.com/pictures/123.png
5、url地址改写
需求(下面是帮朋友配置的):
想把 project.zhszychina.cn/index.php/login 这种登陆方式改写成 project.zhszychina.cn/login 登陆
在nginx的配置文件里面加入一下内容
location / {
if (!-e $request_filename){
rewrite ^(.*)$ /index.php$1 last;
}
}