Nginx 配置location中常见指令详解

629 阅读13分钟

nginx进行转发代理的核心在于两处,一是入口,二是出口;入口就是url路径匹配识别对应的路径,出口就是转发映射对应的后台服务地址

image.png

**【1】 location 指令详解 **

我们的入口路径匹配识别都是在location模块实现的,所以我们要首先认识location支持的匹配模式。location支持2种匹配模式:精确匹配(普通匹配)和模糊匹配(正则匹配),总共以下几种呈现形式:

location简单实例如下:

location / {
        root   html;
        #首页文件。以下按顺序匹配
        index  index.html index.htm;
    }


location语法格式:

location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }

匹配模式

1. 全路径精确匹配 = , 不含正则表达式

= :精确匹配。用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。

进行uri的全路径精确匹配,要匹配的一模一样的uri比如 location = /index ,那么只有路径为/index的才会匹配到

2. 前缀模糊匹配 ^~ , 不含正则表达式

用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。

进行uri的前缀精确匹配比如 location ^~ /user/ ,那么只要是路径以/user/开头的都会匹配到

3. 模糊匹配 ~ 包含正则表达式,区分大小写:

~用于表示 uri 包含正则表达式,,并且区分大小写。

进行uri的模糊匹配,区分大小写,匹配到后不再进行其他匹配

比如 location ~ /user/ ,当路径包含/user/时会匹配,

比如/admin/user/或者/user/admin/当然也可以用正则表达式来表示匹配路径:比如 location ~ ^/user(.*)admin$,能够匹配以/user开头,admin结尾的路径,.*表示的是任意字符

location如果没有“/”时,请求就可以模糊匹配以字符串开头的所有字符串,而有“/”时,只能精确匹配字符本身。 目标访问地址:http://192.168.88.129/edu/index.html

这里我们简单测试一下,配置后我们访问192.168.244.41/user/xxx/admin,发现是可以正常转发至后台的tomcat服务的,只是tomcat服务中没有/user地址的接口,所以返回404

image.png

我们继续访问192.168.244.41/user/xxx,发现报的就是nginx的404了,这说明请求并没有转发到后台tomcat中,说明没有命中匹配。

image.png

在比如实例如下

  location ~  /edu/ {
	proxy_pass http://127.0.0.1:8080;
	}
	
 location ~  /edu {
	proxy_pass http://127.0.0.1:8080;
	}

/edu 可以匹配/edu*/*格式的路径URL,而/edu/ 只能匹配/edu/*格式的URL。这里注意到proxy_pass后面没有加/也没有加目录,则会把location的值直接拼接到proxy_pass后面。

4. 模糊匹配 ~* 包含正则表达式,不区分大小写:

用于表示 uri 包含正则表达式,并且不区分大小写,即看到~就表示正则表达式。

image.png

进行uri的模糊匹配,不区分大小写,匹配到后不再进行其他匹配,优先级与~相同,按照先后顺序优先****

比如 location ~ /USER/,当路径包含/USER/时会匹配,如果是/user/则不会,因为区分大小写了****

优先级:****

5.不带符号精确匹配

匹配起始于此uri的所有的url

没有符号,按照路径开头精确匹配,但是匹配到后不会立即返回,还会继续匹配其他普通匹配,如果匹配到,则会舍弃之前匹配的路径

比如 location /user/ , 当访问/user/开头时会匹配到

比如 location /user/admin,当访问/user/admin时会匹配到

注意事项:

  1. 如果 uri 包含正则表达式,则必须要有 ~ 或者 ~* 标识

  2. 匹配优先级:由高到低为 = > ^~ > 其他,其他匹配根据先后顺序,配置在前的越优先

匹配优先级=, ^~, ~/~*,不带符号

  • 精确匹配=
  • 前缀匹配^~(立刻停止后续的正则搜索)
  • 按文件中顺序的正则匹配~或~*
  • 匹配不带任何修饰的前缀匹配。

实例

location = / {
    [ configuration A ]
}

location / {
    [ configuration B ]
}

location /documents/ {
    [ configuration C ]
}

location ^~ /images/ {
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
    [ configuration E ]
}

/匹配规则A,“/index.html”匹配规则B,“/documents/document.html”匹配规则C, “/images/1.gif”匹配规则D,“/documents/1.jpg”匹配规则E。

【2】 转发代理 proxy_pass指令 配置详解

我们上述讲解了匹配模式的书写,匹配到了还要进行合理的转发,而转发模式的控制就是通过proxy_pass, 下面我们来看看proxy_pass的语法结构

proxy_pass 的四种配置写法 首先我们来回顾下proxy_pass的语法:

1.proxy_pass url;

转发地址url分为带/和不带/,带杠的为绝对根路径,会直接在路径后拼接上不带匹配路径的转发地址;如果没有杠表示相对路径,则会将匹配路径也带上进行转发,我们举例说明:

1.location /user/ {
    proxy_pass url;
  }

访问路径固定为:http://192.168.244.21/user/index.html

  1. 当proxy_pass http://192.168.244.21:8080/ 时,会跳转至http://192.168.244.21:8080/index.html,带/表示绝对路径,匹配路径/user/会被消除

  2. 当proxy_pass http://192.168.244.21:8080 时, ,相对路径 ,会跳转至http://192.168.244.21:8080/user/index.html,匹配路径/user/不会被消除,

3.当proxy_pass http://192.168.244.21:8080/admin/ 时 会跳转至http://192.168.244.21:8080/admin/index.html,匹配路径/user/被消除,并且保留转发路径里的/admin/

4.当proxy_pass http://192.168.244.21:8080/admin 时

会跳转至http://192.168.244.21:8080/adminindex.html,因为proxy_pass中也包含了/了,表示绝对路径,所以/user/会被消除

总言之记住一点,带/表示绝对路径,请求路径中的匹配路径(location)转发时会被消除;

server和location模块中proxy_pass的区别

  • 在server模块中的proxy_pass只需要配置ip(或域名)和端口,相当于端口转发;
  • 在location中的proxy_pass,也就是我们更加常用的,可以配置域名、ip、端口、uri,此外还需要提供协议:http或https,相当于地址转发。

配置语法如下:

server {

listen 80;
proxy_responses 1;
proxy_timeout 20s;
proxy_pass xxx.com:8080;
# proxy_pass 192.168.244.21:8080;

    location /user/ {
        roxy_pass http://192.168.244.21:8081;
    }
}

【3】# 文件路径指令 root与alias

NGINX配置中,root 和 alias 是两个用于指定文件路径的指令,它们用于将URL路径映射到服务器上的文件系统路径。尽管它们的目的相似,但它们的行为和用法有所不同。

location ${path} {
    root html; # 会将${path}一起加入到代理的(/html/${path})路径中
    alias html; # 不会将${path}一起加入到代理的(html/)路径中
}

root path

root 设置web资源路径映射, 指令用于定义请求的根目录。NGINX会将请求的URI附加到root指令指定的路径上,以构建文件系统的路径,用于指明用户请求的url所对应的本地文件系统上的文档所在目录路径,可指定相对路径也可使用绝对路径。

可用的位置:http, server, location, if in location。

实例如下

location /images/ {
	root /data/www;  
}

如果用户请求 /images/example.jpg,NGINX会在/data/www/images/example.jpg中查找文件。

如请求/i/top.gif,则按照如下配置目标文件为/data/w3/i/top.gif:

location /i/ {
    root /data/w3;
}

alias path

alias 指令也用于定义请求的根目录,但它不会将请求的URI附加到指定的路径上。相反,它使用指定的路径替换URI中的位置部分

实例一 :

为指定路径 定义一个替代值,仅能用于location上下文。

如访问/i/top.gif,按照如下location配置,则目标文件为/data/w3/images/top.gif :

location /i/ {
    alias /data/w3/images/;
}

实例二

location /images/ {
	alias /data/www/static/;  
}

在这个例子中,如果用户请求 /images/example.jpg,NGINX会在/data/www/static/example.jpg中查找文件,而不是在/data/www/static/images/example.jpg中。

使用场景

  • 当你的目录结构和URL结构一致时,使用root。
  • 当你的目录结构和URL结构不一致时,使用alias。

注意事项 在使用alias时,要特别注意末尾的斜杠(/)。

    - 如果alias的路径以斜杠结尾,那么请求的URI中匹配location的部分将会被替换掉;
    - 如果不以斜杠结尾,那么请求的URI中匹配location的部分将会被替换并保留到最后一个斜杠。

root通常比alias更安全,因为它不会允许访问服务器上的任意目录。而alias如果不正确使用,可能会导致安全漏洞。 在使用这两个指令时,请确保你完全理解它们的行为,并根据你的具体需求进行选择。

location中使用: root指令和alias指令的意义不同:

  • root,目标文件路径为root指定的value+URI;
  • alias,给定的路径对应于location中的/uri/右侧的/

也就是说当使用root指令时,文件的路径构造只是把URI的值拼接在了root指令值的后面!

在使用这两个指令时,请确保你完全理解它们的行为,并根据你的具体需求进行选择。

【4】 设置处理请求的策略 try_files

image.png

示例

  #对象组件前端
        location /object-component/ui {
            alias /home/bom/deploy/frontend/object_component_web;
            index index.html index.htm;
            try_files $uri $uri/ /index.html last;
        }
        #xbom前端组件
        location /bom-web {
            alias /home/xbom/deploy/frontend/bom-web;
            index index.html index.htm;
            try_files $uri $uri/ /index.html last;
        }

几点说明:

  1. 按指定的file顺序查找存在的文件,并使用第一个找到的文件进行请求处理
  2. 查找路径是按照给定的root或alias为根路径来查找的
  3. 如果给出的file都没有匹配到,则重新请求最后一个参数给定的uri,就是新的location匹配
  4. 如果最后一个参数是 = 404 ,若给出的file都没有匹配到,则最后返回404的响应码

示例

$uri 是请求文件的路径,$uri/ 是请求目录的路径。

最后一个参数也可以指向一个命名的位置,如下面的示例所示。从版本0.7.51开始,最后一个参数也可以是code如404。

#参数: $uri 表示当前请求的URI,不带任何参数

location /mall/ {
  root   htmlmall;
  index  index.html index.htm;
  try_files $uri $uri/ /mall/index.html =404;
}

假设说请求是/mall/images/1.jpg:

① nginx会先去找/htmlmall/mall/images/1.jpg这个文件,

② 如果①找不到则会找/htmlmall/mall/images/1.jpg/这个目录下的index索引页

③ 如果②也没找到,则会去请求/mall/index.html—一个新的请求

④ 如果③也没找到,返回404

注意,如果try-files 如果不写上 $uri/,当直接访问一个目录路径时,并不会去匹配目录下的索引页。 即 访问127.0.0.1/mall/images不会去访问 127.0.0.1/mall/images/index.html 。

如果想实现项目直接解压部署在htmlmall下,不再创建一个mall文件夹的话,root换成alias即可。

【5】 动静分离之静态资源映射配置

为了提高网站反应速率,一般用于中小型网站,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源,如图片、js、css等文件,可以在反向代理服务器中进行缓存,这样浏览器在请求一个静态资源时,代理服务器就可以直接处理,而不用将请求转发给后端服务器。对于用户请求的动态文件,如servlet、jsp,则转发给Tomcat,Jboss服务器处理,这就是动静分离。即动态文件与静态文件的分离。

动静分离可通过location对请求url进行匹配,将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。通常将静态资源放到nginx中,动态资源转发到tomcat服务器中。

在Nginx中进行动静分离,通常需要配置两个location块:一个用于处理静态资源的请求,另一个用于将所有其他请求转发到后端服务器。以下是一个简单的配置示例:

server {
    listen 80;
    server_name example.com;
 
    # 静态资源的根目录
    root /path/to/static/files;
 
    # 静态文件的location块
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|html|htm)$ {
        expires 30d; # 设置静态文件的缓存过期时间
        add_header Cache-Control "public";
    }
 
    # 处理所有其他请求的location块
    location / {
        proxy_pass http://backend_server; # 假设后端服务器地址是http://backend_server
        include proxy_params; # 假设proxy_params文件包含了一些代理设置参数
    }
}

在这个配置中,所有.jpg.jpeg.png.gif.ico.css.js.html.htm等静态资源的请求都会被Nginx直接处理,并设置30天的缓存。其他所有请求都会被转发到名为backend_server的后端服务器。

请根据实际情况调整root指令中的静态文件目录和proxy_pass中的后端服务器地址。

通过 expires 参数设置,可以使浏览器缓存过期时间,减少与服务器之前的请求和流量。具体 Expires 定义:是给一个资源设定一个过期时间,也就是说无需去 服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用 Expires 来缓存)

示例二 这里以图片实例,将图片存储在/usr/local/nginx/image路径下。

nginx配置文件实例如下:

 location ~* .(jpg|png|jpeg)$ {
        root /usr/local/nginx/;
        expires 3d;
}

如这里设置 3d ,表示在这 3 天之内访问这个 URL ,发送一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码 304如果有修改,则直接从服务器重新下载,返回状态码 200 。

浏览器访问如下http://192.168.88.129/image/1.jpg

image.png

这里需要注意浏览器访问uri是/image/1.jpg,这个location拦截后会拼接到root后去服务器找,也就是 /usr/local/nginx/image/1.jpg

示例三

worker_processes 1;

events { worker_connections 1024; }

http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65;

#定义一组服务器 upstream httpds{ server 172.16.70.222:8080; server 172.16.70.223:8080; } server { listen 80; server_name www.jiang.com;

    location / {
        proxy_pass http://httpds;
        #root   /www/proxy;
        #index  index.html index.htm;
    }

    location ~*/(images|assets) {
        root   /www/resources;
        index  index.html index.htm;
    }

#将图片和样式以正则表达式来表现出来 #location /assets {

        #root   /www/resources;
        #index  index.html index.htm;
    #}

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

}

}

【6】 autoIndex指令 展示文件路径目录下内容

如下所示,访问image路径然后展示其下(location里面映射的路径)的文件列表。

autoindex模块它所实现的一个基本功能,是当用户请求以 / 结尾式的URL,它会列出对应的目录结构

  • 比如说, 在实际的生态环境中,内部系统可能经常需要为用户提供一些下载功能。
  • 可能需要列出来某一个磁盘上的一个文件, 比如,磁盘上是一个视频目录文件
  • 在访问某一个特定的目录的URL的时候,会给用户列出来所有视频文件
  • 这个时候,通常就会使用到autoindex这样一个功能

1)指令集

1.1 autoindex

  • 语法:autoindex on | off;
  • 默认值:autoindex off
  • 上下文:http、server、location
  • 默认情况下是不打开这样一个功能的
  • 因为这样一个功能对我们的用户来说,会有很多隐藏信息
  • 在对一些特定的内网环境,可能是有用的
  • 比如说,我们的公司内部可能经常需要下载一些文件,分享一些文档
  • 使用这样一个功能,就可以很好的去搭建这样一个下载平台

1.2 autodindex_exact_size

  • 语法:autodindex_exact_size on | off;
  • 默认值:autodindex_exact_size off
        • 上下文:http、server、location
      • 默认情况下,它是一个on的一个指令,文件的大小,它会精确到字节,以字节为单位的
    • 把这个功能给关闭掉,字节很大的话,比如说50M,它小的话, 比如显示150Byte,或者更大的话,能显示来GB
  • 关闭后,使我们这个文件大小更直观,更友好

1.3 autoindex_format

  • 语法:autoindex_format html | xml | json | jsonp;
  • 默认值:autoindex_format html;
  • 上下文:http、server、location
  • 就是返回目录结构的时候,以哪种形式返回
  • 经常会用的是html 还有 xml/json/jsonp等
  • 这样一些格式我们都是可选的

1.4 autoindex_localtime

  • 语法:autoindex_localtime on | off;
  • 默认值:autoindex_localtime off;
  • 上下文:http、server、location
  • 这个决定文件的一个时间格式,默认情况下开off,它就显示GMT的格式

image.png

这里需要用到autoindex 指令,也就是ngx_http_autoindex_module 模块。其往往用于处理以/结尾的请求并展示一个路径下内容列表。配置实例如下:

示例一

 location /image/ {
	root /usr/local/nginx/;
	autoindex on;
}

也可以返回json格式:

  location /image/ {
	root /usr/local/nginx/;
	autoindex on;
	autoindex_format json;
 }

image.png

示例二

server {
	listen 		80;
	server 		name       www.baidu.com
	location /download/  {
		root /opt/source;
		index b.html;
		
		autoindex on;
		autoindex exact size on;
		autoindex format html;
		autoindex localtime off;
}

注意,download/b.html 不存在, 如果存在,则下面配置会失效

image.png 注意,如果 autoindex exact size off; 关闭,就会显示的更人性化

image.png

  • 注意,除了 html, 其他格式均不支持下载

【7】 add_header 指令 添加/覆盖响应头

add_header 是 Nginx 中用于设置 HTTP 响应头的指令,它通常位于 serverlocation 或者 http 级别的上下文中。

基本语法如下:

add_header name value;

其中 name 是响应头的名称,value 是响应头的值。

配置示例

server {
    listen 80;
    server_name example.com;
 
    location / {
        add_header X-My-Header "My Value";
        proxy_pass http://backend;
    }
}

在这个例子中,对于所有通过该 location 的请求,Nginx 将添加一个名为 X-My-Header 的响应头,其值为 My Value

注意:

  • add_header 不会覆盖已有的响应头,除非使用了 always 参数。
  • 如果 value 包含变量,确保变量名用花括号 {} 包围,以避免语法混淆。
add_header X-My-Header "My $value";

在这个例子中,$value 是一个变量,它的值将被插入到响应头 X-My-Header 中。

示例二

http {
    # 添加一个新的头部
    add_header X-Custom-Header "CustomValue";

    server {
        listen 80;

        # 修改现有的头部
        add_header Content-Type text/html;

        # 条件性地添加头部
        if ($request_method = GET) {
            add_header X-Method-Type "GET";
        }

        location / {
            # 代理请求时添加头部
            proxy_pass http://backend;
            proxy_set_header Host $host;
            add_header X-Proxy-Used "true";
        }
    }
}

这个例子中,我们添加了自定义的 HTTP 头部 X-Custom-Header ,修改了 Content-Type 头部,并且根据请求方法添加了条件性的头部 X-Method-Type 。在代理请求时,我们添加了 X-Proxy-Used 头部以表明请求是通过 Nginx 代理的。 请注意, add_header 指令应该放在 http 、 server 或 location 块中,具体取决于你想要在哪个级别上添加或修改头部。

【8】 proxy_set_header 指令 修改请求/添加请求头

proxy_set_header 指令在 Nginx 中用于设置或重置从代理服务器传递到目标服务器的请求头。这可以用来修改或添加请求头,以便传递给后端服务。

以下是一些常用的 proxy_set_header 配置示例:

  1. 默认情况下,proxy_set_header 会设置 Host 为被代理的主机,但你可以重写它:
location / {
    proxy_set_header Host $host;
    proxy_pass http://backend;
}
  1. 如果你想要传递原始的主机名到后端服务器,可以使用 $http_host 变量:
location / {
    proxy_set_header Host $http_host;
    proxy_pass http://backend;
}

3.你也可以设置 X-Real-IP 头来传递客户端的原始 IP 地址

location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_pass http://backend;
}

4.如果你想要传递客户端的 IP 地址给后端服务器,但不想使用 $remote_addr 变量,可以使用 X-Forwarded-For 头:

location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://backend;
}
  1. 如果你想要修改 Cookie 头,可以使用 proxy_set_header
location / {
    proxy_set_header Cookie "";
    proxy_pass http://backend;
}

6.如果你想要添加一个新的头部信息:

location / {
    proxy_set_header X-Custom-Header "some-value";
    proxy_pass http://backend;
}
  • add_header 与 proxy_set_header两者区别
    • 方向:proxy_set_header 修改的是请求头(request header),而 add_header 修改的是响应头(response header)
    • 目标:proxy_set_header 的目标是后端服务器,用于通知后端关于请求的一些信息;而 add_header 的目标是客户端,用于向客户端提供额外的信息或指令
    • 使用场景:proxy_set_header 通常在反向代理配置中使用,确保后端服务器能正确处理请求;而add_header 在需要向客户端发送额外信息或增强安全性的情况下使用