nginx之location规则及地址重写


一、location规则

1、什么是location?

  nginx就是通过拦截到的请求去对配置好的location块(location block)进行请求代理的。被代理的URL去对location后边的字符串(或正则)进行匹配,根据一定的规则选择走哪个location。

2、location语法规则

  语法:location [=|^~|~|~*|@] /uri/ { … }

  其中,红色字段为前缀符号,各个前缀符号表达不同的含义。而对于这些前缀符号,分为两类:普通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/ 将精确匹配到 B_rule。

在这里插入图片描述

   访问 http://www.a.com/1/ 将精确匹配 C_rule。

在这里插入图片描述
   访问 http://www.a.com/1/2/ 将最大前缀匹配 D_rule。

在这里插入图片描述

   访问 http://www.a.com/1/2/index.html 将首先最大前缀匹配到 D_rule,但是会被后面的正则匹配 G_rule 覆盖。

在这里插入图片描述
   访问 http://www.a.com/test.html 匹配到 E_rule 后,就不再继续匹配。

在这里插入图片描述

   访问 http://www.a.com/test.png 将根据正则location顺序匹配到 I_rule。

在这里插入图片描述
   访问 http://www.a.com/3 都将匹配不上,所以走 A_rule 的默认规则。

在这里插入图片描述

二、地址重写

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;:
}
  • 25
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值