文章目录

  • 一、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/

nginx替换模块 nginx location 替换_正则

   访问 http://www.a.com/1/

nginx替换模块 nginx location 替换_正则_02


   访问 http://www.a.com/1/2/

nginx替换模块 nginx location 替换_html_03

   访问 http://www.a.com/1/2/index.html

nginx替换模块 nginx location 替换_nginx替换模块_04


   访问 http://www.a.com/test.html

nginx替换模块 nginx location 替换_正则_05

   访问 http://www.a.com/test.png

nginx替换模块 nginx location 替换_nginx_06


   访问 http://www.a.com/3

nginx替换模块 nginx location 替换_nginx替换模块_07

二、地址重写

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;
    }
}

nginx替换模块 nginx location 替换_html_08

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;:
}