Nginx 重写功能(location / rewrite)

发布时间 2023-03-27 16:41:56作者: menglang
 

一、Nginx常见模块

  • http

    http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这模块中。作用包括:文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。

  • server

    server块,虚拟主机(虚拟服务器)。作用:使得Nginx服务器可以在同一台服务器上只要运行一组Nginx进程,就可以运行多个网站。

  • location

    location块是server块的一个指令。作用:基于Nginx服务器接收到的请求字符串,虚拟主机名称(ip,域名)、url匹配,对特定请求进行处理。

 

二、访问路由location

2.1 location常用正则表达式

匹配符表示含义
^ 匹配输入字符串的起始位置
$ 匹配输入字符串的结束位置
* 匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll”
+ 匹配前面的字符一次或多次。如“ol+”能匹配“ol”及“oll”、“olll”,但不能匹配“o”
? 匹配前面的字符零次或一次,例如“do(es)?”能匹配“do”或者“does”,”?”等效于”{0,1}”
. 表示任意一个字符
\转义字符 用于取消特殊符号的含义
\d 匹配纯数字
\s 匹配空的(空格或者制表符)
{n} 匹配前面的子表达式n次
{n,} 匹配前面的子表达式不少于n次
{n,m} 匹配前面的子表达式n到m次
[ ] 匹配括号中的一个字符
[c] 匹配单个字符 c
[a-z] 匹配 a-z 小写字母的任意一个
[a-zA-Z0-9] 匹配所有大小写字母或数字
() 表达式的开始和结束位置
| 或运算符

 

2.2location的分类

  • 精准匹配:location = / {}

  • 一般匹配:location / {}

  • 正则匹配:location ~ / {}

 

2.3location 常用的匹配规则

规则表达式规则含义
= 进行普通字符精确匹配。也就是完全匹配
^~ 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他 location
~ 表示执行一个正则匹配,区分大小写
~* 表示执行一个正则匹配,不区分大小写
!~ 表示执行一个正则匹配,区分大小写不匹配
!~* 表示执行一个正则匹配,不区分大小写不匹配

 

2.4location优先级排列说明

  1. 首先精确匹配 =

  2. 其次前缀匹配 ^~

  3. 其次是按文件中顺序的正则匹配 ~或~*

  4. 然后匹配不带任何修饰的前缀匹配

  5. 最后是交给 / 通用匹配

  1.  
    location = / {
  2.  
    [ configuration A ]
  3.  
    }
  4.  
     
  5.  
    location / {
  6.  
    [ configuration B ]
  7.  
    }
  8.  
     
  9.  
    location /documents/ {
  10.  
    [ configuration C ]
  11.  
    }
  12.  
     
  13.  
    location ^~ /images/ {
  14.  
    [ configuration D ]
  15.  
    }
  16.  
     
  17.  
    location ~* \.(gif|jpg|jpeg)$ {
  18.  
    [ configuration E ]
  19.  
    }

 

2.5location 示例

(1)精确匹配

  1.  
    location = / {}
  2.  
    =为精确匹配 / , 主机名后不能携带任何字符串,比如 / 和 /data ,则/匹配,/data不匹配

 

(2)一般匹配/通用匹配

  1.  
    location / {}
  2.  
    代表以/开头,所以这条规则将匹配所有的请求
  1.  
    location /documents/ {}
  2.  
    匹配任何以/documents/开头的地址,匹配符合后,还会继续往下搜索其他 location,只有其它location后面的正则表达式没有匹配到时,才会用这一条
  1.  
    location /documents/abc {}
  2.  
    匹配任何以/documents/abc开头的地址,匹配符合后,还会继续往下搜索其他 location,只有其它location后面的正则表达式没有匹配到时,才会用这一条

 

(3)正则匹配

  1.  
    location ^~ /images/ {}
  2.  
    匹配任何已/images/ 开头的地址,匹配符合后,停止往下搜索,采用这一条
  1.  
    location ~* \.(gif|jpg|jpeg)$ {}
  2.  
    匹配所有 gif jpg 或 jepg 结尾的请求
  3.  
    如果 有上面的location ^~ /images/ {}匹配 则会先匹配上一请求,所以到不了这一条。

 

2.6location 优先级总结

如果是匹配某个具体文件: (location = 完整路径) > (location ^~ 完整路径) > (location ~* 完整路径) >(location ~ 完整路径) > (location /)通用匹配

 

2.7实例

2.7.1location = / {} 与 location / {}

实例1:location = / {} 和 location / {} ,按道理应匹配前者,但实际确实匹配后者,匹配只写域名精确匹配不生效,接下来一个小例子说明一下

  1.  
    1. #在配置文件添加匹规则
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
     
  4.  
    #添加的网页
  5.  
    location = / {
  6.  
    root /web/dog/;
  7.  
    }
  8.  
     
  9.  
    #默认网页
  10.  
    location / {
  11.  
    root html;
  12.  
    index index.html index.htm; }
  13.  
     
  14.  
    2. #新建网页站点目录
  15.  
    mkdir -p /web/dog
  16.  
     
  17.  
    3. #在站点目录下新建index.html
  18.  
    vim /web/dog/index.html
  19.  
     
  20.  
    this is dog web
  21.  
     
  22.  
    4. #检查语法并重启
  23.  
    nginx -t
  24.  
    systemctl restart nginx.service
  25.  
     
  26.  
    5. #在网页中测试
  27.  
    http://192.168.59.118/
  28.  
     

在配置文件添加匹规则

 

 

新建网页站点目录,新建index.html文件

检查语法并重启

 

 

在网页中测试

 

 

 

2.7.2 location = /index.html {} 与 location / {}

在 根后 加上index.html 后生效

  1.  
    1. #修改一下配置文件
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
     
  4.  
    location = /index.html { # 加上index.html
  5.  
    root /web/dog/;
  6.  
    }
  7.  
     
  8.  
     
  9.  
    2. #重启服务,并网页中测试
  10.  
    systemctl restart nginx.service
  11.  
     
  12.  
     
  13.  
     
  14.  
     

 

 

2.7.3location = /1.jpg {} 和 location ~* .(gif|jpg|png|jpeg)$ {}比较

  1.  
    1. #修改一下配置文件
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
     
  4.  
    location = /1.jpg {
  5.  
    root /web/dog/; #小狗的网页
  6.  
    }
  7.  
     
  8.  
    location ~* \.(jpg|gif|png) {
  9.  
    root /web/cat/; #小猫的网页
  10.  
    }
  11.  
     
  12.  
    2. #在刚刚创建的dog的站点下添加图片
  13.  
    cd /web/dog/
  14.  
    拖入图片
  15.  
     
  16.  
    3. #新建一个cat目录,添加图片
  17.  
    mkdir cat
  18.  
    cd cat
  19.  
    拖入图片
  20.  
     
  21.  
     
  22.  
    4. #检查语法,重启服务
  23.  
    nginx -t
  24.  
    nginx -s reload
  25.  
     
  26.  
    5. #在网页中测试
  27.  
    http://192.168.59.118/1.jpg
  28.  
    结果可以看出=精确匹配

修改配置文件

 

 

在刚刚创建的dog的站点下添加图片

 

 

 

新建一个cat目录,添加图片

 

 

 

 

在网页中测试

 

 

 

2.7.4大小写问题

  1.  
    1. #修改配置文件
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
     
  4.  
    location ~ /A.?\.jpg {
  5.  
    root /web/image;
  6.  
    index index.html index.htm;
  7.  
    }
  8.  
     
  9.  
     
  10.  
    2. #新建站点目录并拖入图片
  11.  
    cd /web
  12.  
    mkdir image
  13.  
    cd image/
  14.  
    拖入图片,然后改名为A.jpg
  15.  
    mv a.webp A.jpg
  16.  
     
  17.  
    3. #重启并在网页中测试
  18.  
    nginx -s reload
  19.  
     

修改配置文件

 

 

 

新建站点目录并拖入图片

 

 

 

重启后,测试

 

 

 

 

 

 

 

  1.  
    1 .#在Linux中将A.jpg拷贝一份命名为a.jpg
  2.  
    cd /web/image/
  3.  
    cp A.jpg a.jpg
  4.  
     
  5.  
    2. #修改配置文件
  6.  
    vim /usr/local/nginx/conf/nginx.conf
  7.  
     
  8.  
    location ~* /A.?\.jpg {
  9.  
    root /web/image;
  10.  
    index index.html index.htm;
  11.  
    }
  12.  
     
  13.  
    3. #重启服务并测试
  14.  
    nginx -s reload
  15.  
    http://192.168.59.118/a.jpg

在Linux中将A.jpg拷贝一份命名为a.jpg

 

 

修改配置文件

 

 

 

重启再测试

 

 

 

2.8实际网站使用中的三个匹配规则定义

第一个规则

  • 直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网。

  • 可以是一个静态首页,也可以直接转发给后端应用服务器

  1.  
    location = / {
  2.  
    root html;
  3.  
    index index.html index.htm;
  4.  
    }

 

第二个规则

是处理静态文件请求,这是nginx作为http服务器的强项有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用。

  1.  
    location ^~ /static/ {
  2.  
    root /webroot/static/ ;
  3.  
    }
  4.  
     
  5.  
    location ~* \.(gif|jpg|jpeg)$ {
  6.  
    root /webroot/static/ ;
  7.  
    }

 

第三个规则

就是通用规则,比如用来转发带.php、.jsp后缀的动态请求到后端应用服务器。

  1.  
    location / {
  2.  
    proxy_pass http://tomcat_server;
  3.  
    }

 

三、REWRITE模块

现在 Nginx 已经成为很多公司作为前端反向代理服务器的首选,在实际工作中往往会 遇到很多跳转(重写 URL)的需求。比如更换域名后需要保持旧的域名能跳转到新的域名 上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。如果在后端使用的 Apache 服务器,虽然也能做跳转,规则库也很强大,但是用 Nginx 跳转效率会更高,这也是学习 本章的目的所在。

 

3.1rewrite功能

rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。比如:更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。

  1.  
    rewrite 只能在
  2.  
    server {}
  3.  
    location {}
  4.  
    if {}
  5.  
    中,并且默认只能对域名后边的除去传递的参数外的字符串起作用
  6.  
    例如:
  7.  
    http://www.yxp.com/abc/bbs/index.html?a=1&b=2 只针对/abc/bbs/index.html重写

 

3.2Rewrite 跳转场景

Rewrite 跳转场景主要包括以下几种

  1. 可以调整用户浏览的 URL,看起来更规范,合乎开发及产品人员的需求

  2. 为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态 URL 地址伪装成静态地址提供服务

  3. 网址换新域名后,让旧的访问跳转到新的域名上。例如,访问京东的 360buy.com会跳转到 jd.com

  4. 根据特殊变量、目录、客户端的信息进行 URL 调整等。

 

3.3Rewrite 跳转实现

  • Nginx 是通过 ngx_http_rewrite_module 模块支持 url 重写、支持 if 条件判断,但不支 持 else。

  • 另外该模块需要 PCRE 支持,应在编译 Nginx 时指定 PCRE 支持,默认已经安装。

  • 根据相关变量重定向和选择不同的配置,从一个 location 跳转到另一个 location,不过这样 的循环最多可以执行 10 次,超过后 Nginx 将返回 500 错误。

  • 同时,重写模块包含 set 指令,来创建新的变量并设其值,这在有些情景下非常有用的,如记录条件标识、传递参数到其他location、记录做了什么等等。

 

3.4Rewrite 执行顺序

  1. 执行server块里面的rewrite指令。

  2. 执行location 匹配。

  3. 执行选定的location中的rewrite指令。

 

3.5Rewrite 语法格式

  1.  
    rewrite <regex> <replacement> [flag];
  2.  
    regex:表示正则匹配规则
  3.  
    replacement:表示跳转后的内容
  4.  
    flag:表示rewrite 支持的 flag 标记
  5.  
     
  6.  
    flag 标记说明:
  7.  
    last:本条规则匹配完成后,继续向下匹配新的location URL规则,一般用在server和if中
  8.  
     
  9.  
    break:本条规则匹配完成即终止,不再匹配后面的任何规则。一般用在location中
  10.  
     
  11.  
    redirect:返回 302 临时重定向,浏览器地址会显示跳转后的 URL 地址,爬虫不会更新 url(因为是临时)。
  12.  
     
  13.  
    permanent:返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址,爬虫更新 url。

 

3.6 Rewrite 实例

3.6.1基于域名的跳转

例如现在访问的是 域名yxp.com启用了顺米网shunmi.com的DNS服务!,现在需要将这个域名下面的发帖都跳转到 http://www.dhc.com,注意保持域名跳转后的参数不变。

  1.  
    1. #修改配置文件
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
     
  4.  
    server {
  5.  
    listen 80;
  6.  
    server_name www.yxp.com;
  7.  
     
  8.  
    charset utf-8;
  9.  
     
  10.  
    #access_log logs/host.access.log main;
  11.  
     
  12.  
    location / {
  13.  
    root html;
  14.  
    index index.html index.htm;
  15.  
    }
  16.  
     
  17.  
    location /index.html {
  18.  
    if ($host = 'www.yxp.com') {
  19.  
    rewrite ^/(.*)$ http://www.dhc.com/$1 permanent;
  20.  
    }
  21.  
    root /web/test;
  22.  
    }
  23.  
     
  24.  
    2. #新建站点目录
  25.  
    mkdir /web/test
  26.  
     
  27.  
    3. #新建文件
  28.  
    vim /web/test/index.html
  29.  
    this is test web!!!
  30.  
     
  31.  
    4. #重启服务
  32.  
    nginx -s reload
  33.  
     
  34.  
     
  35.  
    5. #另外开一台虚拟机,修改/etc/hosts文件
  36.  
    vim /etc/hosts
  37.  
    192.168.59.118 www.yxp.com www.dhc.com
  38.  
     
  39.  
    6. #打开新开的虚拟机的浏览器网页测试
  40.  
    http://www.yxp.com

修改配置文件

 

 

 

新建站点目录和文件

 

 

重启服务

 

 

 

另外开一台虚拟机,修改/etc/hosts文件

 

 

 

 

在网页测试

 

 

 

3.6.2基于客户端IP 访问跳转

  1.  
    1. #修改配置文件
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
     
  4.  
    server {
  5.  
    listen 80;
  6.  
    server_name www.yxp.com;
  7.  
     
  8.  
    charset utf-8;
  9.  
     
  10.  
    #access_log logs/host.access.log main;
  11.  
    set $rewrite true;
  12.  
    if ($remote_addr = '192.168.91.103'){
  13.  
    set $rewrite false;
  14.  
    }
  15.  
    if ($rewrite = true){
  16.  
    rewrite (.+) /weihu.html;
  17.  
    }
  18.  
     
  19.  
    location /weihu.html {
  20.  
    root /var/www/html;
  21.  
    }
  22.  
     
  23.  
    location / {
  24.  
    root html;
  25.  
    index index.html index.htm;
  26.  
    }
  27.  
     
  28.  
    2. #新建站点目录及文件
  29.  
    mkdir -p /var/www/html
  30.  
    vim /var/www/html/weihu.html
  31.  
     
  32.  
    we are busing now,please wait for a moment!
  33.  
     
  34.  
    3. #重启服务 nginx -s reload
  35.  
     
  36.  
    4. #在网页测试
  37.  
    http://192.168.59.118/

修改配置文件

 

 

 

 

新建站点目录及文件

 

 

 

重启服务后在网页测试

 

 

 

 

3.6.3基于旧域名跳转到新域名后面加目录

例如现在访问的是 http://bbs.yxp.com/post 现在需要将这个域名下面的发帖都跳转到 http://www.yxp.com/bbs/post,注意保持域名跳转 后的参数不变。

  1.  
    1. #修改配置文件
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
    server {
  4.  
    listen 80;
  5.  
    server_name www.yxp.com;
  6.  
     
  7.  
    charset utf-80;
  8.  
     
  9.  
    #access_log logs/host.access.log main;
  10.  
    location /post {
  11.  
    rewrite (.+) http://www.yxp.com/bbs$1 permanent;
  12.  
    }
  13.  
     
  14.  
    location / {
  15.  
    root html;
  16.  
    index index.html index.htm;
  17.  
    }
  18.  
     
  19.  
    2. #新建站点目录,并创建文件
  20.  
    mkdir -p /usr/local/nginx/html/bbs/post
  21.  
    vim /usr/local/nginx/html/bbs/post/index.html
  22.  
     
  23.  
    this is the test!!
  24.  
     
  25.  
    3. #开一台服务器,修改/etc/hosts文件
  26.  
    vim /etc/hosts
  27.  
    192.168.59.118 www.yxp.com www.dhc.com bbs.yxp.com
  28.  
     
  29.  
    4. #重启服务并在浏览器中测试
  30.  
    nginx -s reload
  31.  
    http://bbs.yxp.com/post

修改配置文件

 

 

新建站点目录

 

 

 

创建文件

 

 

 

开一台服务器,修改/etc/hosts文件

 

 

 

重启服务并在浏览器中测试

 

 

 

 

3.6.4基于参数匹配的跳转

http://www.yxp.com/100-(100|200)-100.html 跳转到 域名yxp.com启用了顺米网shunmi.com的DNS服务! 页面

  1.  
    1. #修改配置文件
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
     
  4.  
    server {
  5.  
    listen 80;
  6.  
    server_name www.yxp.com;
  7.  
     
  8.  
    charset utf-8;
  9.  
     
  10.  
    #access_log logs/host.access.log main;
  11.  
    location ~ /100-(100|200)-(\d+).html$ {
  12.  
    rewrite (.+) http://www.kgc.com permanent;
  13.  
    }
  14.  
     
  15.  
    location / {
  16.  
    root html;
  17.  
    index index.html index.htm;
  18.  
    }
  19.  
     
  20.  
     
  21.  
    2. #重启服务
  22.  
    nginx -s reload
  23.  
     
  24.  
    3. #验证
  25.  
    http://www.yxp.com/100-100-100

修改配置文件

 

 

 

重启服务

 

 

验证

 

 

3.6.5基于 目录下所有的php文件

要求访问 http://www.yxp.com/upload/123.php 跳转到首页

  1.  
    1. #修改配置文件
  2.  
    vim /usr/local/nginx/conf/nginx.conf
  3.  
     
  4.  
    server {
  5.  
    listen 80;
  6.  
    server_name www.yxp.com;
  7.  
     
  8.  
    charset utf-8;
  9.  
     
  10.  
    #access_log logs/host.access.log main;
  11.  
    location ~* /upload/.*\.php$ {
  12.  
    rewrite (.+) http://www.yxp.com permanent;
  13.  
    }
  14.  
     
  15.  
    location / {
  16.  
    root html;
  17.  
    index index.html index.htm;
  18.  
    }
  19.  
     
  20.  
    2. #重启服务
  21.  
    systemctl restart nginx
  22.  
     
  23.  
    3. #在网页测试
  24.  
    http://www.yxp.com/upload/123.php

修改配置文件

 

 

 

重启服务

 

 

 

在网页测试

 

 

 

3.6.6基于 普通的一条url

要求访问一个具体的页面 如 http://www.yxp.com/abc/123.html 跳转到首页

  1.  
    1. #修改配置文件
  2.  
    server {
  3.  
    listen 80;
  4.  
    server_name www.yxp.com;
  5.  
     
  6.  
    charset utf-8;
  7.  
     
  8.  
    #access_log logs/host.access.log main;
  9.  
    location ~* ^/abc/123.html$ {
  10.  
    rewrite (.+) http://www.yxp.com permanent;
  11.  
    }
  12.  
     
  13.  
    location / {
  14.  
    root html;
  15.  
    index index.html index.htm;
  16.  
    }
  17.  
     
  18.  
    2. #重启服务
  19.  
    systemctl restart nginx.service
  20.  
     
  21.  
    3. #在网页测试
  22.  
    http://www.yxp.com/abc/123.html

 

修改配置文件

 

 

 

重启服务

 

 

 

在网页测试