nginx入门之Rewrite
Rewrite 是nginx服务器提供的一个重要功能,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。
一、正则表达式
rewrite的核心是PCRE。下面看看几个常用的正则表达式语法:
*
: 0次或者多次前面的字符或子表达式;
+
: 1次或者多次前面的字符或子表达式;
?
: 0次或者1次前面的字符或子表达式;
^
: 匹配搜索字符串开始的位置;
$
: 匹配搜索字符串结束的位置;
.
: 匹配除\n 之外的任何单个字符;
[]
: 标记括号表达式的开始和结尾;
{}
: 标记限定表达式的开始和结尾;
()
: 标记子表达式的开始和结尾 ;
|
: 指示在两个或者多个中做选择;
二、rewrite
rewrite只能放在server{},location{},if{}中,只对URI起作用(去除域名和参数)。
模块指令处理处理顺序:
- 执行server块的rewrite指令;
- 执行location匹配;
- 执行选定的location中的rewrite指令,如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件,如果循环超过10次,则返回500 Internal Server Error错误
2.1 指令
break
停止执行当前虚拟主机的后续rewrite指令集
作用域:server, location, if
示例:
location / {
if( $slow){
set $id $1 # 配置有效
break;
limit_rate 10k; #配置无效
}
... # 配置有效
}
if
作用域:server,location
对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行。 if条件(conditon)可以是如下任何内容:
- 一个变量名;false, 如果这个变量是空字符串或者以0开始的字符串;
- 使用
=
,!=
比较的一个变量和字符串 - 使用
~
,~*
: 正则表达式匹配,后者表示不区分大小写。 - 使用-f ,!-f 检查一个文件是否存在
- 使用-d, !-d 检查一个目录是否存在
- 使用-e ,!-e 检查一个文件、目录、符号链接是否存在
- 使用-x , !-x 检查一个文件是否可执行
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
}
if ($request_method = POST) {
return 405;
}
if ($slow) {
limit_rate 10k;
}
if ($invalid_referer) {
return 403;
}
return
改指令用于完成对请求的处理,直接向客户端返回响应状态码;
作用域:server, location, if
return [text]
return code URL;
return URL;
- text: 响应体内容,支撑变量
- URL: 返回给客户端的URL地址
- code: 状态码
rewrite
通过正则表达式改变URI。
Syntax: rewrite regex replacement [flag]; Default: — Context: server, location, if
- regex: 使用正则表达式,使用’()‘标记要截取的内容。
- replacement: 匹配成功后替换URI中被截取的部分。
- flag: 用来设置rewrite对URI的处理行为。有
last
,break
,redirect
,permanent
flag 标志
- last : 表示完成rewrite
- break : 停止执行当前虚拟主机的后续rewrite指令集
- redirect : 返回302临时重定向,地址栏会显示跳转后的地址
- permanent : 返回301永久重定向,地址栏会显示跳转后的地址
三、rewrite使用
3.1 三级域名跳转
server{
listen 80;
server_name jump1.myweb.name jump2.myweb.name;
if ($http_host ~* ^(.*)\.myweb\.name$)
{
rewrite ^(.*) http://jump.myweb.name$1;
break;
}
}
3.2 域名镜像
server{
listen 80;
server_name jump.myweb.name;
location ^~ /source1 { #找到,停止匹配其他 location
rewrite ^/source1(.*) http://jump.myweb.name/websrc2$1 last;
}
location ^~ /source2 {
rewrite ^/source2(.*) http://jump.myweb.name/websrc2$1 last;
}
}
3.3 独立域名
server{
listen 80;
server_name bbs.myweb.name;
rewrite ^(.*) http://www.myweb.name/bbs$1 last;
break;
}
server{
listen 81;
server_name home.myweb.name;
rewrite ^(.*) http://www.myweb.name/home$1 last;
break;
}
3.4 目录自动加 “/”
server{
listen 80;
server_name www.myweb.name;
location ^~ /bbs {
if (-d $request_filename){
# 把uri各个部分取出来重新拼装,后面跟上"/" permanent永久重定向
rewrite ^(.*)/(.*)([^/])$ http://$host/$1$2/ permanent;
}
}
}
四、rewrite全局变量
下面是可以用作if判断的全局变量:
- $args: 这个变量等于请求行中的参数,同
$query_string
- $content_length : 请求头中的Content-length字段。
- $content_type : 请求头中的Content-Type字段。
- $document_root : 当前请求在root指令中指定的值。
- $host : 请求主机头字段,否则为服务器名称。
- $http_user_agent : 客户端agent信息
- $http_cookie : 客户端cookie信息
- $limit_rate : 这个变量可以限制连接速率。
- $request_method : 客户端请求的动作,通常为GET或POST。
- $remote_addr : 客户端的IP地址。
- $remote_port : 客户端的端口。
- $remote_user : 已经经过Auth Basic Module验证的用户名。
- $request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
- $scheme : HTTP方法(如http,https)。
- $server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
- $server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
- $server_name : 服务器名称。
- $server_port : 请求到达服务器的端口号。
- $request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
- $uri: 不带请求参数的当前URI,
$uri
不包含主机名,如”/foo/bar.html”。 - $document_uri: 与
$uri
相同。
例:http://localhost:88/test1/test2/test.php
- $host:localhost
- $server_port:88
- $request_uri:http://localhost:88/test1/test2/test.php
- $document_uri:/test1/test2/test.php
- $document_root:/var/www/html
- $request_filename:/var/www/html/test1/test2/test.php