ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

nginx rewrite

2020-08-13 09:34:18  阅读:281  来源: 互联网

标签:请求 rewrite nginx html 模块 root


目录

nginx rewrite

Nginx工作原理

nginx由内核和模块组成

模块由结构分为:

核心模块: HTTP 模块、EVENT 模块和 MAIL 模块

基础模块: HTTP Access 模块、HTTP FastCGI 模块、HTTP Proxy 模块和 HTTP Rewrite 模块

第三方模块: HTTP Upstream Request Hash 模块、Notice 模块和 HTTP Access Key 模块

由功能分为:

Handlers(处理器模块): 此类模块直接处理请求,并进行输出内容和修改 headers 信息等操作。Handlers 处理器模块一般只能有一个

Filters(过滤器模块):此类模块主要对其他处理器模块输出的内容进行修改操作,最后由 Nginx 输出

Proxies(代理类模块): 此类模块是 Nginx 的 HTTP Upstream 之类的模块,这些模块主要与后端一些服务比如FastCGI 等进行交互,实现服务代理和负载均衡等功能。

Rewrite模块

NGX http rewrite_module官方文档

ngx_http_rewrite_module模块用于使用PCRE正则表达式更改请求URI,返回页面重定向,和按条件选择配置。

ngx_http_rewrite_module模块指令按以下顺序处理:

  • 处理在server级别中定义的模块指令;
  • 为请求查找location;
  • 处理在选中的location中定义的模块指令。如果指令改变了URI,按新的URI查找location。这个循环至多重复10次,之后nginx返回错误500 (Internal Server Error)。

语法:

语法:**rewrite** *regex* *replacement* [*flag*];
默认值:—

上下文:server, location, if

如果指定的正则表达式能匹配URI,此URI将被*replacement*参数定义的字符串改写。

rewrite指令按其在配置文件中出现的顺序执行。flag可以终止后续指令的执行。

如果replacement的字符串以“http://”或“https://”开头,nginx将结束执行过程,并返回给客户端一个重定向。

例如:

语法:rewrite regex replacement flag;,如:

rewrite ^/images/(.*\.jpg)$ /imgs/$1 break;

此处的$1用于引用(.*.jpg)匹配到的内容,又如:

rewrite ^/bbs/(.*)$ http://www.idfsoft.com/index.html redirect;

如上例所示,replacement可以是某个路径,也可以是某个URL

可选的*flag*参数:

flag 作用
last 基本上都用这个flag,表示当前的匹配结束,继续下一个匹配,最多匹配10个到20个 一旦此rewrite规则重写完成后,就不再被后面其它的rewrite规则进行处理 而是由UserAgent重新对重写后的URL再一次发起请求,并从头开始执行类似的过程
break 中止Rewrite,不再继续匹配 一旦此rewrite规则重写完成后,由UserAgent对新的URL重新发起请求, 且不再会被当前location内的任何rewrite规则所检查
redirect 以临时重定向的HTTP状态302返回新的URL
permanent 以永久重定向的HTTP状态301返回新的URL

rewrite模块的作用是用来执行URL重定向。这个机制有利于去掉恶意访问的url,也有利于搜索引擎优化(SEO)

nginx使用的语法源于Perl兼容正则表达式(PCRE)库,基本语法如下:

标识符 意义
^ 必须以^后的实体开头
$ 必须以$前的实体结尾
. 匹配任意字符
[] 匹配指定字符集内的任意字符
[^] 匹配任何不包括在指定字符集内的任意字符串
| 匹配 | 之前或之后的实体
() 分组,组成一组用于匹配的实体,通常会有 | 来协助

捕获子表达式,可以捕获放在()之间的任何文本,比如:

^(hello|sir)$       //字符串为“hi sir”捕获的结果:$1=hi$2=sir

//这些被捕获的数据,在后面就可以当变量一样使用了

模块应用场景:

地址跳转,例如换新域名后,让旧域名跳转到新域名上

协议跳转,用户通过http协议请求网站时,将其重新跳转至https协议方式

伪静态,很多企业会将动态URL地址伪装成静态地址提供服务,减少过多的参数暴露

搜索引擎,SEO优化依赖于url路径,好记的url便于智齿搜索引擎录入

企业会将动态URL地址伪装成静态地址提供服务

网址换新域名后,让旧的访问跳转到新的域名.上

服务端某些业务调整

实例

#nginx的默认根目录下的images目录没有数据,而/opt/imgs下有名字加1.jpg的图片
[root@www ~]# ls /usr/local/nginx/html/images/
[root@www ~]# ls /opt/imgs/
1.jpg

#当访问images下以.jpg结尾的文件时转到/opt/imgs下的.jpg文件

......
        location / {
            root   html;
            index  index.html index.htm;
        }
		location /images {
            root    /opt;
            rewrite ^/images/(.*\.jpg)$ /imgs/$1 break;
        }
......


URI是/images/1.jpg,而/images下是没有数据的,说明确实跳转到了/opt/imgs/1.jpg

也可以用last这样写

[root@www ~]# vim /usr/local/nginx/conf/nginx.conf
......
        location / {
            root   html;
            index  index.html index.htm;
        }
        location /images {
            rewrite ^/images/(.*\.jpg)$ /imgs/$1 last;
        }
        location /imgs {
            root /opt;
        }
[root@www ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@www ~]# nginx -s reload
......

一样可以访问,这里在处理last之前的指令集时,会停止处理后续rewrite指令集,跳出当前的location作用域,并开始搜索与更改后的URI相匹配的location,同时URL地址是不变的

if

Syntax: if (condition) { ... }
Default: —
Context: server, location

计算指定的condition的值。如果为真,执行定义在大括号中的rewrite模块指令,并将if指令中的配置指定给请求。if指令会从上一层配置中继承配置。

条件可以是下列任意一种:

  • 变量名;如果变量值为空或者是以“0”开始的字符串,则条件为假;
  • 使用“=”和“!=”运算符比较变量和字符串;
  • 使用“~”和“~*” (区分大小写和不区分大小写)运算符匹配变量和正则表达式。正则表达式可以包含匹配组,匹配结果后续可以使用变量$1..$9引用。如果正则表达式中包含字符“}”或者“;”,整个表达式应该被包含在单引号或双引号的引用中。
  • 使用“-f”和“!-f”运算符检查文件是否存在;
  • 使用“-d”和“!-d”运算符检查目录是否存在;
  • 使用“-e”和“!-e”运算符检查文件、目录或符号链接是否存在;
  • 使用“-x”和“!-x”运算符检查可执行文件;

nginx一些内置变量

变量名 说明
$arg_name 指URL请求中的参数,name是参数的名字
$args 代表URL中所有请求的参数
$binary_remote_addr 客户端地址以二进制数据的形式出现,通常会和限速模块一起使用
$body_bytes_sent 发送给客户端的字节数,不包含响应头
$bytes_set 发送给客户端的字节总数
$document_uri 设置$uri的别名
$hostname 运行Nginx的服务器名
$http_referer 表示请求是从哪个页面链接过来的
$http_user_agent 客户端浏览器的相关信息
$remote_addt 客户端IP地址
$remote_port 客户端端口号
$remote_user 客户端用户名,通常在Auth Basic模块中使用
$request_filename 请求的文件路径,基于root alias指令和URI请求生成
$request_time 请求被nginx接收后,一直到相应数据返回给客户端所用时间
$request_uri 请求的URI,带参数
$request 记录请求的URL和HTTP
$request_length 请求的长度,包括请求行、请求头和请求正文
$server_name 虚拟主机的server_name的值,通常是域名
$server_port 服务器端口号
$server_addr 服务器的IP地址
$request_method 请求的方式,如GET、POST
$scheme 请求的协议,如HTTP、HTTPS
$sent_http_name 任意响应头,name为响应头的名字,注意name要小写
$realip_remote_addr 保留原来的客户地址,在real_ip模块中使用
$server_protocol 请求采用的协议名称和版本号,常为HTTP/1.0或HTTP1.1
$uri 当前请求的URI,在请求过程中URI可能会改变,例如在内部重定向或使用索引文件时
$nginx_version Nginx版本号
$pid worker进程的PID
$pipe 如果请求是HTTP流水线发送的,pipe值为“p”,否则为“.”
$connection_request 当前通过一个连接获得的请求数量
$cookie_name name即Cookie名字,可得到Cookie信息
$status HTTP请求状态
$msec 日志写入时间。单位为秒,经度为毫秒
$time_local 在通用日志格式下的本地时间
$upstream_addr 请求反向代理到后端服务器的IP地址
$upstream_port 请求反向代理到后端服务器的端口号
$upstream_response_time 请求在后端服务器消耗的时间
$upstream_status 请求在后端你服务器的HTTP响应状态
$geoip_city 城市名称,在geoip模块中使用

基于浏览器实现分离案例

[root@www ~]# mkdir /usr/local/nginx/html/{QQBrowse,Edg,Chrome}
[root@www ~]# echo 'QQBrowse test page..........' > /usr/local/nginx/html/QQBrowser/index.html
[root@www ~]# echo 'EdgBrowser test page..........' > /usr/local/nginx/html/Edg/index.html
[root@www ~]# echo 'ChromeBrowser test page..........' > /usr/local/nginx/html/Chrome/index.html



[root@www ~]# vim /usr/local/nginx/conf/nginx.conf
......
        location / {


            if ($http_user_agent ~ Edg) {
                rewrite ^(.*)$ /Edg/$1 break;
            }

            if ($http_user_agent ~ Chrome) {
                rewrite ^(.*)$ /Chrome/$1 break;
            }

            root   html;
            index  index.html index.htm;
        }


        location /Edg {
            root   html;
            index  index.html;
        }
        location /Chrome {
            root   html;
            index  index.html;
        }
 


......

[root@www ~]# nginx -s reload

谷歌浏览器访问

微软浏览器访问

防盗链案例

如果来源不是www.test.com的就返回403

location ~* \.(jpg|gif|jpeg|png)$ {
  valid_referers none blocked server_names www.test.com;
  if ($invalid_referer) {
    return 403;
    #rewrite ^/ http://www.test.com/403.html;
  }
}

1、none

"Referer" 来源头部为空的情况

2、blocked

"Referer"来源头部不为空,但是里面的值被代理或者防火墙删除了,这些值都不以http://或者https://开头.

3、server_names

"Referer"来源头部包含当前的server_names(当前域名)

标签:请求,rewrite,nginx,html,模块,root
来源: https://www.cnblogs.com/shipment/p/13492270.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有