nginx入门之Rewrite

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, redirectpermanent

flag 标志

  1. last : 表示完成rewrite
  2. break : 停止执行当前虚拟主机的后续rewrite指令集
  3. redirect : 返回302临时重定向,地址栏会显示跳转后的地址
  4. 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

CONTENTS