文章目录
- 一、location规则
- 1、什么是location?
- 2、location语法规则
- 3、匹配顺序问题
- 4、location实例
- 二、地址重写
- 1、什么是地址重写?
- 2、应用场景
- 3、如何使用?
- 4、rewrite实例
一、location规则
1、什么是location?
nginx就是通过拦截到的请求去对配置好的location块(location block)进行请求代理的。被代理的URL去对location后边的字符串(或正则)进行匹配,根据一定的规则选择走哪个location。
2、location语法规则
语法:location [=|^~|~|~*|@]
其中,红色字段为前缀符号,各个前缀符号表达不同的含义。而对于这些前缀符号,分为两类:普通location和正则location。\~
和 ~*
前缀表示正则location ,其他前缀(比如:=、^~ 和 @
)和无任何前缀的都属于普通location 。
符 号 | 含 义 |
location = /uri | = 表示精确匹配,只有完全匹配上才能生效,优先级最高 |
location ^~ /uri | ^~ 表示最大前缀匹配,不做正则匹配检查 |
location ~ pattern | ~ 表示区分大小写的正则匹配 |
location ~* pattern | ~* 表示不区分大小写的正则匹配 |
location / | / 表示通用匹配,任何未匹配到其它location的请求都会匹配到 |
3、匹配顺序问题
匹配之间存在优先级:= > ^~ > ~|~* > /
① 在nginx配置文件中一般会定义多个location,对于一个特定的HTTP请求,到底应该匹配哪一个location呢(匹配先后顺序)?答案是:先匹配普通location,再匹配正则location。
② 那么问题又来了,在多个普通location之间是如何匹配的呢?答案是:最大前缀匹配。什么意思呢?举个例子:对一个HTTP请求/www.a.com/nginx/static/test.html进行前缀匹配," location /nginx/ {} " 和 " location /nginx/static/ {} " 两个都满足,根据我们所说的最大前缀匹配,所以选择" location /nginx/static/ {} "。
③ 同样,多个正则location之前如何匹配的呢?答案是:按照正则location在配置文件中的顺序,如果匹配到一条正则location,那么就不再考虑后面的规则。
④ 在普通location进行了最大前缀匹配后,如果匹配到了一条location,并不意味着结束,这只是作为临时的结果,nginx还要继续检查后面的正则location,如果正则location也有匹配上的,那么正则location会覆盖普通location。
⑤ 但是你想在匹配到普通location后,不再需要继续匹配也是可以的。你只需要在普通location前加上 " ^~ "(^表示非,~表示正则)或 " = "(严格匹配),都可以终止后面的匹配。
4、location实例
配置文件中location块的解释:
########### 每个指令必须有分号结束。#################
location [=|^~|\~|\~*|@] {
#root path; #根目录
#index test.html; #设置默认页
#proxy_pass http://mysvr; #转发动态请求到后端应用服务器mysvr
}
这里我们修改虚拟主机a的配置进行演示。
[root@nginx-server ~]# vim /etc/nginx/conf.d/a.conf
server {
listen 192.168.140.142:80;
server_name www.a.com;
access_log /data/a/log/access.log combined;
location / {
echo "A_rule /";
}
location =/ {
echo "B_rule = /";
}
location /1/ {
echo "C_rule /1/";
}
location /1/2/ {
echo "D_rule /1/2/";
}
location /1/2/test.html {
echo "E_rule /1/2/test.html";
}
location ~ \.html$ {
echo "G_rule .html";
}
location ~* \.png$ {
echo "I_rule all:png";
}
location ~ \.(gif|jpg|png|js|css)$ {
echo "H_rule gif|jpg|png|js|css";
}
}
匹配结果是这样的:
① 访问 http://www.a.com/
② 访问 http://www.a.com/1/
③ 访问 http://www.a.com/1/2/
④ 访问 http://www.a.com/1/2/index.html
⑤ 访问 http://www.a.com/test.html
⑥ 访问 http://www.a.com/test.png
⑦ 访问 http://www.a.com/3
二、地址重写
1、什么是地址重写?
Rewrite又称URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程。
2、应用场景
① 伪静态化,是将动态页面显示为静态页面方式的一种技术。理论上,搜索引擎更喜欢静态页面形式的网页,搜索引擎对静态页面的评分一般要高于动态页面。所以,URL Rewrite可以让我们网站的网页更容易被搜索引擎所收录。
② 提高安全性,如果在URL中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的URL地址可以给我们带来更高的安全性。
③ 美化URL,去除一些后缀名或参数串,让网页的地址看起来尽可能简洁明快,有利于反映访问模块内容。
④ 实现地址跳转、协议跳转、端口跳转。
3、如何使用?
Nginx Rewrite相关指令有if、rewrite、set、return等。我们先来认识这些指令以及几个常用的全局变量,再通过实例来深入学习。
① rewrite 指令
应用环境:server、location、if;
语法:rewrite regex replacement [flag]
- regex:表示使用正则或字符串来匹配相应的地址
- replacement:表示重定向的地址
- flag:标志位,用于控制当匹配到对应的rewrite规则后是否继续检查后续的rewrite规则,flag的值可以是:
flag | 描 述 |
last | 本条规则匹配完成后,停止匹配,将重写后的地址重新发起请求进行匹配,浏览器地址栏URL地址不变 |
break | 本条规则匹配完成后,停止匹配,不再匹配后面的规则 |
redirect | 返回302临时重定向,地址栏会显示跳转后的地址 |
permanent | 返回301永久重定向,地址栏会显示跳转后的地址 |
redirect与permanent区别: 对于客户端来说一般状态下是没有区别的。而对于搜索引擎,相对来说301的重定向更加友好,如果我们把一个地址采用301跳转方式跳转的话,搜索引擎会把老地址的相关信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。使用302重定向时,搜索引擎(特别是google)有时会查看跳转前后哪个网址更直观,然后决定显示哪个,如果它觉的跳转前的URL更好的话,也许地址栏不会更改,那么很有可能出现URL劫持的现像。在做URI重写时,有时会发现URI中含有相关参数,如果需要将这些参数保存下来,并且在重写过程中重新引用,可以使用 () 和 $N 的方式来解决。
② if 指令(判断语句)
应用环境:server、location;
语法:if (condition) { … }
其中condition就是条件,如果为true,则执行大括号中的内容。if支持的条件判断匹配符号如下:
条件判断匹配符 | |
=!= | 比较变量和字符串是否相等/相同 |
~ | 匹配正则表达式(区分大小写) |
~* | 匹配正则表达式(不区分大小写) |
!~!~* | 可以理解为"与正则表达式不匹配时返回真",与上面同理,一个区分大小写,一个不区分大小写; |
-f!-f | 判断文件是否存在 |
-d!-d | 判断目录是否存在 |
-e!-e | 判断文件或目录是否存在 |
-x!-x | 判断文件是否可执行 |
tip:当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false。
③ set 指令(定义一个新的变量)
应用环境:server、location、if;
语法:set variable_name value
- variable_name:变量名称
- value:变量值
④ return 指令(结束执行配置语句并为客户端返回状态码)
语法:return code
- code:状态码,可以是204,400,402-406,408,410,411,413,416,500-504,默认返回None。
⑤ 常用全局变量
全局变量 | 解 释 |
$host | 请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名 |
$request_filename | 当前请求的文件路径,由root指令所指定的根目录和请求的uri组成 |
$request_uri | 当前请求的文件路径,请求的uri |
你肯定看不懂,我们来测试一下,你就会明白!
[root@nginx-server ~]# vim /etc/nginx/conf.d/a.conf
server {
listen 192.168.140.142:80;
server_name www.a.com;
access_log /data/a/log/access.log combined;
location / {
root /data/a/basic; #根目录
echo $host;
echo $request_filename;
echo $request_uri;
}
}
4、rewrite实例
之前在配置虚拟主机时,已经配置过域名解析,所以可以直接用windows上的浏览器进行测试。
① 访问:http://www.a.com/111/1.html
跳转:http://www.a.com/222/2.html
location /111/ {
rewrite .* /222/2.html permanent;
}
② 访问:http://www.a.com/2015/aaa/bbb/1.html
跳转:http://www.a.com/2014/aaa/bbb/1.html
location /2015/ {
rewrite ^/2015/(.*)$ /2014/$1 permanent;
}
③ 访问:http://www.a.com/
跳转:http://www.b.com/
if ($host ~* www.a.com) {
rewrite .* http://b.com permanent;
}
④ 访问:http://www.a.com/aaa/1.html
跳转:http://www.b.com/aaa/1.html
if ($host ~* www.a.com) {
rewrite .* http://b.com$request_uri permanent;
}
⑤ 在访问目录后添加/ (如果目录后已有/,则不加/)
访问:http://www.a.com/aaa
跳转:http://www.a.com/aaa/
if (-d $request_filename) {
rewrite ^(.*)([^/])$ http://$host$1$2/ permanent;
}
⑥ 访问:http://www.a.com/login/1.html
跳转:http://www.a.com/reg/login.php?user=1
location /login/ {
rewrite ^/login/(.*).html$ /reg/login.php?user=$1 permanent;
}
⑦ 访问:http://www.a.com/uplook/11-22-33.html
跳转:http://www.a.com/uplook/11/22/33.html
location /uplook/ {
rewrite ^/uplook/([0-9]+)-([0-9]+)-([0-9]+)\.html$ /uplook/$1/$2/$3.html permanent;
}
⑧ 访问:http://jack.a.com
跳转:http://www.a.com/jack
这里需要配置域名解析。
记事本打开"C:\Windows\System32\drivers\etc\hosts"文件,在末尾添加"192.168.140.142 jack.a.com" 。
if ($host ~* "^www.a.com$" ) { #如果没有这一条配置,http://jack.a.com重写为http://www.a.com/jack会继续来匹配,导致跳转为http://www.a.com/www。
break;
}
if ($host ~* ^(.*)\.a\.com$) {
set $user $1;
rewrite .* http://www.a.com/$user permanent;
}
⑨ 实现端口跳转
访问:80
跳转:443
server {
listen 80;
server_name www.a.com;
return 301 https://www.a.com$request_uri;
}
server {
listen 443 ssl;
server_name www.a.com;
ssl on; #nginx 1.15及以后的版本,不需要再写 ssl on;
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/cert.key;:
}