Nginx重定向

200次阅读
没有评论

共计 6912 个字符,预计需要花费 18 分钟才能阅读完成。

Rewrite简介

Rewrite是Nginx服务器提供的一个重要基本功能,是Web服务器产品中几乎必备的功能。主要的作用是用来实现URL的重写
注意:Nginx服务器的Rewrite功能的实现依赖于PCRE的支持,因此在编译安装Nginx服务器之前,需要安装PCRE库。Nginx使用的是ngx_http_rewrite_module模块来解析和处理Rewrite功能的相关配置。

  • “地址重写”与”地址转发”

重写和转发的区别:

  1. 地址重写浏览器地址会发生变化而地址转发则不变
  2. 一次地址重写会产生两次请求而一次地址转发只会产生一次请求
  3. 地址重写到的页面必须是一个完整的路径而地址转发则不需要
  4. 地址重写因为是两次请求所以request范围内属性不能传递给新页面,地址转发因为是一次请求所以可以传递值
  5. 地址转发速度快于地址重写

Rewrite规则

Rewrite常用全局变量

变量 说明 案例
$args 变量中存放了请求URL中的请求指令。
功能和$query_string一样 http://172.41.100.15:8088/args?a=1&b=3
$args=a=1&b=3
$http_user_agent 变量存储的是用户访问服务的代理信息
(如果通过浏览器访问,记录的是浏览器的相关版本信息) http_user_agent = Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
$host 变量存储的是访问服务器的server_name值 host =172.41.100.15
$document_uri 变量存储的是当前访问地址的URI。 document_uri =/args
$document_root 变量存储的是当前请求对应location的root值,如果未设置,默认指向Nginx自带html目录所在位置 document_root=/home/nginx/html
$content_length 变量存储的是请求头中的Content-Length的值
$content_type 变量存储的是请求头中的Content-Type的值
$http_cookie 变量存储的是客户端的cookie信息,可以通过add_header Set-Cookie ‘cookieName=cookieValue’来添加cookie数据
$limit_rate 变量中存储的是Nginx服务器对网络连接速率的限制,也就是Nginx配置中对limit_rate指令设置的值,默认是0,不限制。
$remote_addr 变量中存储的是客户端的IP地址 remote_addr=172.41.100.13
$remote_port 变量中存储了客户端与服务端建立连接的端口号 remote_port=50360
$remote_user 变量中存储了客户端的用户名,需要有认证模块才能获取
$scheme 变量中存储了访问协议 scheme =http
$server_addr 变量中存储了服务端的地址 server_addr=172.41.100.15
$server_name 变量中存储了客户端请求到达的服务器的名称 server_name=localhost
$server_port 变量中存储了客户端请求到达服务器的端口号 server_port=8088
$server_protocol 变量中存储了客户端请求协议的版本,比如”HTTP/1.1″ server_protocol=HTTP/1.1
$request_body_file 变量中存储了发给后端服务器的本地文件资源的名称
$request_method 变量中存储了客户端的请求方式,比如”GET”,”POST”等 request_method =GET
$request_filename 变量中存储了当前请求的资源文件的路径名 request_filename =/home/nginx/html/args
$request_uri 变量中存储了当前请求的URI,并且携带请求参数 request_uri=/args?a=1&b=3

set指令

该指令用来设置一个新的变量。

语法 set $variable value;
默认值
位置 server、location、if

variable:变量的名称,变量名称要用”$”作为变量的第一个字符,且不能与Nginx服务器预设的全局变量同名。
value:变量的值,可以是字符串、其他变量或者变量的组合等。

if指令

该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置

语法 if (condition){…}
默认值
位置 server、location

condition为判定条件,可以支持以下写法:

  1. 变量名。如果变量名对应的值为空或者是0,if都判断为false,其他条件为true。
if ($param){
    
}
  1. 使用”=“和”!=”比较变量和字符串是否相等,满足条件为true,不满足为false
if ($request_method = POST){
    return 405;
}

注意:此处和Java不太一样的地方是字符串不需要添加引号

  1. 使用正则表达式对变量进行匹配,匹配成功返回true,否则返回false。变量与正则表达式之间使用”“、”“、”!“、”!“来连接
    1. “~”代表匹配正则表达式过程中区分大小写
    2. “~*”代表匹配正则表达式过程中不区分大小写
    3. “!“和”!*”刚好和上面取相反值,如果匹配上返回false,匹配不上返回true
if ($http_user_agent ~ MSIE){
	#$http_user_agent的值中是否包含MSIE字符串,如果包含返回true
}

注意:正则表达式字符串一般不需要加引号,但是如果字符串中包含”}“或者是”;”等字符时,就需要把引号加上。

  1. 判断请求的文件是否存在使用”-f”和”!-f”,
    当使用”-f”时,如果请求的文件存在返回true,不存在返回false。
    当使用”!-f”时,如果请求文件不存在,但该文件所在目录存在返回true,文件和目录都不存在返回false,如果文件存在返回false
if (-f $request_filename){
	#判断请求的文件是否存在
}
if (!-f $request_filename){
	#判断请求的文件是否不存在
}
  1. 判断请求的目录是否存在使用”-d”和”!-d”,
    当使用”-d”时,如果请求的目录存在,if返回true,如果目录不存在则返回false
    当使用”!-d”时,如果请求的目录不存在但该目录的上级目录存在则返回true,该目录和它上级目录都不存在则返回false,如果请求目录存在也返回false.
  2. 判断请求的目录或者文件是否存在使用”-e”和”!-e”
    当使用”-e”,如果请求的目录或者文件存在时,if返回true,否则返回false.
    当使用”!-e”,如果请求的文件和文件所在路径上的目录都不存在返回true,否则返回false
  3. 判断请求的文件是否可执行使用”-x”和”!-x”
    当使用”-x”,如果请求的文件可执行,if返回true,否则返回false
    当使用”!-x”,如果请求文件不可执行,返回true,否则返回false

break指令

用于中断当前相同作用域中的其他Nginx配置。与该指令处于同一作用域的Nginx配置中,位于它前面的指令配置生效,位于后面的指令配置无效。

语法 break;
默认值
位置 server、location、if
location /{
	if ($param){
		set $id $1;
		break;
    #不生效,限制nginx向客户端每秒传输速率
		limit_rate 10k;
	}
}

return指令

用于完成对请求的处理,直接向客户端返回响应状态代码。在return后的所有Nginx配置都是无效的。

语法 return code [text]; return code URL; return URL;
默认值
位置 server、location、if
  • code:为返回给客户端的HTTP状态代理。可以返回的状态代码为0~999的任意HTTP状态代理
  • text:为返回给客户端的响应体内容,支持变量的使用
  • URL:为返回给客户端的URL地址

rewrite指令

该指令通过正则表达式的使用来改变URI。可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理。

语法 rewrite regex replacement [flag];
默认值
位置 server、location、if

regex:用来匹配URI的正则表达式
replacement:匹配成功后,用于替换URI中被截取内容的字符串。
如果该字符串是以”http://”或者”https://”开头的,则不会继续向下对URI进行其他处理,而是直接返回重写后的URI给客户端。
flag:用来设置rewrite对URI的处理行为,可选值有如下:

  • last: 终止执行rewrite模块指令集,并开始搜寻重写url后匹配的location
  • break:终止执行rewrite模块指令集
  • redirect:临时重定向
  • permanent:永久重定向
  • 案例
server{
  listen  8077;
  server_name localhost;
  location / {
    rewrite ^/test1 /test3 last;
    rewrite ^/test2 /test4 break;
    rewrite ^/test5 /test6 redirect;
    rewrite ^/test7 /test6 permanent;
  }
  location /break/ {
    rewrite ^/break/(.*) /test$1 break;
    # echo需要安装第三方模块 echo-nginx-module
    # git clone https://codechina.csdn.net/mirrors/agentzh/echo-nginx-module.git
    echo "break page";
  } 
  location /test3 {
    return 200 "/test3";
  }
  location /test4 {
    return 200 "/test4";
  }
  location /test6 {
    return 200 "/test6";
  }
}
  • 访问请求
  1. 访问[http://172.41.100.15:8077/test1](http://172.41.100.15:8077/test1) 返回 /test3

访问/test1被重写为/test3,因为flag为last,所以发起一次location匹配,匹配到location /test3 {},所以最终返回结果为http200及/test3;

  1. 访问[http://172.41.100.15:8077/test2](http://172.41.100.15:8077/test2) 返回 404

访问/test2,虽然/test2被重定向到/test4,但是break指令不会重新开启一个新的请求继续匹配,所以nginx是不会匹配到下面的/test/这个location,nginx尝试找/test4这个html页面并输出起内容,事实上,这个页面不存在,所以会报404的错误。可以看error.log

2021/08/18 10:15:19 [error] 29936#0: *7 open() "/home/nginx/html/test4" failed (2: No such file or directory), client: 172.41.100.13, server: localhost, request: "GET /test2 HTTP/1.1", host: "172.41.100.15:8077"
  1. 访问http://172.41.100.15:8077/test5 返回 /test6

访问/test1被重写为/test6,因为flag为redirect,地址栏被重写为http://172.41.100.15:8077/test6http状态码为302 临时重定向,浏览器发起两次请求,一次/test5,一次/test6
Nginx重定向

  1. 访问[http://172.41.100.15:8077/test7](http://172.41.100.15:8077/test5) 返回 /test6

访问/test1被重写为/test7,因为flag为permanent,地址栏被重写为[http://172.41.100.15:8077/test6](http://172.41.100.15:8077/test6) http状态码为301 永久重定向,浏览器发起两次请求,一次/test7,一次/test6
Nginx重定向

  1. 访问http://172.41.100.15:8077/break/6返回 break page

break是跳过当前请求的rewrite阶段,并继续执行本请求的其他阶段,对于/break/对应的content阶段的输出为 echo “break page”;
content阶段,可以简单理解为产生数据输出的阶段,如返回静态页面内容也是在content阶段;echo指令也是运行在content阶段,一般情况下content阶段只能对应一个输出指令,如同一个location配置两个echo,最终只会有一个echo指令被执行;
如果把/break/里的echo 指令注释,然后再次访问/break/xx会报404
虽然/break/xx被重定向到/test/xx,但是break指令不会重新开启一个新的请求继续匹配,所以nginx是不会匹配到下面的/test/这个location;在echo指令被注释的情况下,/break/ 这location里只能执行nginx默认的content指令,即尝试找/test/xx这个html页面并输出起内容,事实上,这个页面不存在,所以会报404的错误。

  • URL和URI的区别:

URI:统一资源标识符
URL:统一资源定位符

rewrite_log指令

配置是否开启URL重写日志的输出功能。

语法 rewrite_log on|off;
默认值 rewrite_log off;
位置 http、server、location、if

开启后,URL重写的相关日志将以notice级别输出到error_log指令配置的日志文件汇总。

  • 案例
server{
        rewrite_log on;
  		  # 重定向error_log地址 
        error_log /home/rewrite.log info;
        listen  8077;
        server_name localhost;
}

日志输出,notice都是重定向日志

Nginx重定向

Nginx教程

配合防盗链使用

使用rewrite将盗链请求转发到自定义的一张图片和页面,给用户比较好的提示信息。

  1. 添加一张图片或者页面做提示展示

在172.41.100.14的nginx目录中添加403图片

Nginx重定向

Nginx教程

  1. 根据防盗链条件重定向盗链请求
server{
 listen 9088;
 server_name localhost;
 location /images {
    valid_referers none blocked server_names 127.0.0.1;
    if ($invalid_referer){
      # 重定向到指定图片
      rewrite ^/ http://172.41.100.14:9088/403/403.jpg;
    }
    root /usr/local/nginx/html;
  }
}

  1. 效果展示

原请求被重定向到403页面了。

Nginx重定向

Nginx教程

目录合并

网站中有一个资源文件的访问路径时 /server/11/22/33/44/20.html,也就是说20.html存在于第5级目录下,如果想要访问该资源文件,客户端的URL地址就要写成 http://172.41.100.15/server/11/22/33/44/20.html,这个是非常不利于SEO搜索引擎优化的,同时客户端也不好记,使用rewrite可以进行如下配置

server {
	listen 80;
	server_name localhost;
	location /server{
		rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+).html$ /server/$1/$2/$3/$4/$5.html last;
	}
}

客户端只需要输入http://172.41.100.15/server-11-22-33-44-20.html就可以访问到20.html页面了。这里也充分利用了rewrite指令支持正则表达式的特性。

正文完
 
yangleduo
版权声明:本站原创文章,由 yangleduo 2023-07-20发表,共计6912字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。