37

Nginx的location指令配置

 3 years ago
source link: http://blog.7rule.com/2018/02/20/nginx-location.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Nginx的location指令配置

Feb 20, 2018

在编写nginx配置中,正确的配置location指令是相当重要的。笔者在一次问题的排查中仔细研究了下这个指令的规则和使用方法,在这里和大家分享一下,如有不正确的地方还望指正。

location [ 限定符 ] 规则uri { 指令集 }

在一个请求的处理流程中,nginx会启动一个location的查找过程,在这个过程中nginx会根据一定的规则用请求的request_uri有选择的去匹配这些定义好的规则uri,之后会找到要应用的唯一的location,并应用这个location定义的指令集中的指令。

这里面最关键的地方,就是location的查找过程是如何进行的。要明白这个过程,首先需要知道规则uri是如何定义的。

规则uri

规则uri分为三种类型,nginx对这几种类型执行的匹配方法是不同的:

1. 对限定符为=的规则执行完全匹配

完全匹配例:location = index.php {},那么仅有请求:http://domain/index.php才能匹配,http://domain/index.phpp或http://domain/iindex.php这种均无法匹配。

2. 对限定符为^~或没有限定符规则执行前缀匹配。

前缀匹配例:location /abc {}或location ^~ /abc {},那么请求:http://domain/abcd、http://domain/abc.php这种均能匹配。

3. 对限定符为~~*的规则执行正则匹配。

正则匹配例:location ~ .php$ {},那么请求:http://domain/abc.php、http://domain/abcd.php这种均可以匹配。

location的查找过程

首先会对所有的等号规则前缀规则进行一次匹配筛选。nginx会在所有的前缀匹配中找到一个最长的匹配,然后记住这个匹配的location。之后会根据这个匹配规则是否有限定符来决定之后的行为:

  1. 如果是等号规则匹配到的,nginx会立即结束查找过程,这个location就是最终结果。

  2. 如果匹配到的规则被限定符^~修饰,则nginx也会结束这个查找过程,这个location就是最终结果。

  3. 如果没有找到匹配或是匹配项没有被限定符修饰,nginx就会进入正则规则的匹配筛选过程。在这个过程中,nginx会按照规则uri在配置中定义的顺序来进行匹配,只要匹配到其中一个,nginx就会立即结束这个匹配过程,这个location也会是最终location。如果没有能找到一个正则匹配,但是之前的前缀匹配成功,那么之前记住的前缀匹配结果则会成为最终结果。

通过上面的查找过程,如果成功找到匹配的location,则会执行执行这个location定义的指令集中的指令。

下面举几个例子来看一下:假设用户均访问http://www.vmc7.com/abc

1. =命中,跳过正则匹配

server {
    listen 80;

    server_name www.vmc7.com;

    location /abc {}

    location = /abc {}

    location ~ /abc {}
}

2. ^~命中,跳过正则匹配

server {

    listen 80;

    server_name www.vmc7.com;

    location /ab {}

    location ^~ /abc {}

    location ~ /abc {}
}

3. 正则命中1,正则匹配优先于前缀匹配

server {
    listen 80;

    server_name www.vmc7.com;

    location /abc {}

    location ~ /ab.* {}
}

4. 正则命中2,正则按顺序匹配

server {
    listen 80;

    server_name www.vmc7.com;

    location /ab {}

    location ~ /ab.* {}
    location ~ /abc {}
}

5. 前缀命中,正则匹配不到,使用之前命中的前缀匹配

server {
    listen 80;

    server_name www.vmc7.com;

    location /abc {}

    location ~ /ef.* {}
}

最后附上伪代码用以描述整个过程

location = findLocation();
if (location != null) {
    runLocationCmdSet();
}
 
function findLocation()
{
    finalLocation  = null;
    prefixLocation = null;
    regexLocation  = null;
 
    prefixLocation = findByPrefix();
    if (prefixLocation != null) {
        if (preceding(prefixLocation) == '=') {
            return prefixLocation;
        }

        if (preceding(prefixLocation) == '^~') {
            return prefixLocation;
        }
    }
 
    regexLocation = findByRegex();
    finalLocation = (regexLocation == null) ? prefixLocation : regexLocation;
 
    return finalLocation;
}
 
function findByPrefix()
{
    result    = null;
    maxLength = 0;
 
    for (location in allPrefixLocation) {
        if ((matchLength = prefixMatch(location))!= 0) {
            if (matchLength > maxLength) {
                maxLength = matchLength;
                result    = location;
            }
        }
    }
 
    return result;
}
 
function findByRegex()
{
    for (location in allRegexLocation) {
        if (regexMatch(location)) {
            return location;
        }
    }
 
    return null;
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK