如何在Nginx中正确地配置Location?

Nginx中location指令的作用是根据用户请求的URI来执行不同的应用,根据用户请求的网站地址URI进行匹配,匹配成功即进行相关的操作。在nginx的 ngxhttpcore_module模块的location标签的匹配原则之前,我要先介绍一下nginx的echo模块,它可以帮助我们检测配置的location标签是否正确,是否达到配置的目的。

如何在Nginx中正确地配置Location?

编译安装echo模块

Nginx的echo模块介绍

echo模块是中国人编写的nginx的第三方模块,可以在Nginx中用来输出一些信息,是在调试排错过程中一个比较好的工具。安装此模块后可以在nginx的url访问中,用echo命令输出字符到用户的浏览器中,可用于检测nginx的配置的正确性。

echo模块的动态添加

  • nginx原软件安装目录:/application/nginx1.8.1
  • nginx软件包的位置:/home/oldboy/tools/nginx-1.8.1
mkdir -p /home/oldboy/tools/
cd !$
wget https://github.com/openresty/echo-nginx-module/archive/v0.60.tar.gz
tar zxf v0.60.tar.gz

查看以前安装的nginx的编译参数

[root@localhost nginx]# /application/nginx/sbin/nginx -V
nginx version: nginx/1.8.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/application/nginx1.8.1 --with-http_stub_status_module --with-http_ssl_module --with-http_dav_module --with-file-aio

进入以前下载过的Nginx安装包目录下重新编译

cd /home/oldboy/tools/nginx-1.8.1
./configure --add-module=/home/oldboy/tools/echo-nginx-module-0.60 --user=nginx --group=nginx --prefix=/application/nginx1.8.1 --with-http_stub_status_module --with-http_ssl_module --with-http_dav_module --with-file-aio

然后make

注意:这里只有make,一定不要执行了make install,不然会覆盖安装 make执行完成后,会在当前目录下生成objs目录,其中的nginx文件即为新的二进制文件,再将原来的二进制文件替换掉就可以了。

备份原来的nginx二进制文件

mv /application/nginx/sbin/nginx /application/nginx/sbin/nginx_bak
cp -a /home/oldboy/tools/nginx-1.8.1/objs/nginx /application/nginx/sbin/

正确性检查

/application/nginx/sbin/nginx -t

到这里nginx的echo模块就已经安装完成了。

ngxhttpcore_module模块是nginx实际处理请求的模块, 在处理请求时,会有很多的变量,这些变量可以通过访问日志记录下来,也可以用于echo 模块进行输出。

举例:

如何在Nginx中正确地配置Location?

nginx的配置文件

 location / {
echo 'query_string: $query_string';
echo 'request_method: $request_method';
echo 'content_type: $content_type';
echo 'content_length: $content_length';
echo 'fastcgi_script_name: $fastcgi_script_name';
echo 'request_uri: $request_uri';
echo 'document_uri: $document_uri';
echo 'document_root: $document_root';
echo 'server_protocol: $server_protocol';
echo 'https: $https';
echo 'nginx_version: $nginx_version';
echo 'remote_addr: $remote_addr';
echo 'remote_port: $remote_port';
echo 'server_addr: $server_addr';
echo 'server_port: $server_port';
echo 'server_name: $server_name';
echo 'uri: $uri';
}

请求结果:

[root@localhost conf]# curl www.xyz.com/index.php?from=jdilong --header "content-type:text/html;" -H "content-length:200"
query_string: from=jdilong
request_method: GET
content_type: text/html;
content_length: 200
fastcgi_script_name: /index.php
request_uri: /index.php?from=jdilong
document_uri: /index.php
document_root: /application/nginx1.8.1/html
server_protocol: HTTP/1.1
https:
nginx_version: 1.8.1
remote_addr: 192.168.229.196
remote_port: 46786
server_addr: 192.168.229.196
server_port: 80
server_name: www.xyz.com
uri: /index.php

注意: 如果echo后边有配置return 或者配置 proxy_pass,则echo的输出会被覆盖,即浏览器无法看到echo的内容。

location标签配置

nginx配置文件中用server标签设置虚拟服务器

server {
listen address[:PORT]|PORT;
server_name SERVER_NAME;
root /PATH/TO/DOCUMENT_ROOT;
}

listen设置监听端口和IP

例如:

listen 192.168.0.100:8000; # 监听192.168.0.100的8000端口
listen 192.168.0.100; # 监听192.168.0.100,不写端口则默认为80端口
listen 8000; # 监听本地8000端口
listen *:8000; # 同上
listen localhost:8000; # 监听127.0.0.1的80端口
listen [::]:8000; # 监听本地的ipv6的8000端口
listen [::1]; # 监听本地的ipv6地址,不写端口则默认为80

server_name设置虚拟服务器名字

虚拟主机的主机名称后可跟多个由空白字符分隔的字符串。 支持*通配任意长度的任意字符

server_name .xyz.com www.xyz.

location匹配模式及顺序

如何在Nginx中正确地配置Location?

location的语法规则如下

location = /uri
┬ ┬ ┬
│ │ │
│ │ │
│ │ │
│ │ │
│ │ └─────────────── 前缀|正则
│ └──────────────────── 可选的修饰符(用于匹配模式及优先级)
└───────────────────────── 必须

修饰符说明及优先级顺序

以下从上到下,第一个优先级最高。

= | location = /uri #开头表示精确匹配,只有完全匹配上才能生效
^~ | location ^~ /uri #开头对URL路径进行前缀匹配,并且在正则之前
~ | location ~ pattern #开头表示区分大小写的正则匹配
~* | location ~* pattern #开头表示不区分大小写的正则匹配
/uri | location /uri #不带任何修饰符
@ | location @err #用于定义一个 Location 块,且该块不能被外部 Client 所访问,只能被nginx内部配置指令所访问

注意:前缀匹配,如果有包含关系时,按最大匹配原则进行匹配。比如在前缀匹配:location /dir01 与 location /dir01/dir02,如有请求 http://localhost/dir01/dir02/file 将最终匹配到 location /dir01/dir02

测试:

location = / {
echo "= /";
}
location = /login {
echo "= /login";
}
location ^~ /static/ {
echo "^~ /static/";
}
location ^~ /static/files {
echo "^~ /static/files";
}
location ~ .(gif|jpg|png|js|css)$ {
echo "~ .(gif|jpg|png|js|css)";
}
location ~* .png$ {
echo "~* .png";
}
location /img {
echo "/img";
}
location / {
echo "/";
}

访问结果:

[root@www conf]# curl http://localhost
= /
[root@www conf]# curl http://localhost/login
= /login
[root@www conf]# curl http://localhost/ofo
/
[root@www conf]# curl http://localhost/static/abc.html
^~ /static/
[root@www conf]# curl http://localhost/static/files/abac.html
^~ /static/files
[root@www conf]# curl http://localhost/a.gif
~ .(gif|jpg|png|js|css)
[root@www conf]# curl http://localhost/b.png
~ .(gif|jpg|png|js|css)
[root@www conf]# curl http://localhost/static/c.png
^~ /static/
[root@www conf]# curl http://localhost/d.PNG
~* .png
[root@www conf]# curl http://localhost/img/e.gif
~ .(gif|jpg|png|js|css)
[root@www conf]# curl http://localhost/img/a.hello
/img
[root@www conf]# curl http://localhost/people/id/1
/
[root@www conf]#

注意:

进行前缀匹配时,会先一直找到最长的前缀匹配,然后看该前缀匹配有没有前置的^~ 修饰符,如果没有^~ 修饰符就接着去查找正则匹配,查找到匹配正则匹配后执行该location。如果最长前缀匹配有^~修饰符则命中该location,不回去匹配其他的正则匹配location;列子如下:

如何在Nginx中正确地配置Location?

请求 http://localhost/static/files/test.jpg 命中规则C,如果规则B有 ^~修饰符,则会命中规则B;

location ^~ /static/ {
echo "规则A";
}
location /static/files {
echo "规则B";
}
location ~ .(gif|jpg|png|js|css)$ {
echo "规则C }

原文始发于:如何在Nginx中正确地配置Location?