nginx 常用全局变量
变量 说明
:-------- :-----
$args //请求中的参数,如www.123.com/1.php?a=1&b=2的$args就是a=1&b=2
$content_length //HTTP请求信息里的"Content-Length"
$conten_type //HTTP请求信息里的"Content-Type"
$document_root //nginx虚拟主机配置文件中的root参数对应的值
$document_uri //当前请求中不包含指令的URI,如www.123.com/1.php?a=1&b=2的$document_uri就是1.php,不包含后面的参数
$host //主机头,也就是域名,请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称
$http_user_agent //客户端的详细信息,也就是浏览器的标识,用curl -A可以指定
$http_cookie //客户端的cookie信息
$limit_rate //如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0
$remote_addr //客户端的公网ip
$remote_port //客户端的端口
$remote_user //如果nginx有配置认证,该变量代表客户端认证的用户名
$request_body_file //做反向代理时发给后端服务器的本地资源的名称
$request_method //请求资源的方式,GET/PUT/DELETE等
$request_filename //当前请求的资源文件的路径名称,相当于是$document_root/$document_uri的组合
$request_uri //请求的链接,包括$document_uri和$args
$scheme //请求的协议,如ftp,http,https
$server_protocol //客户端请求资源使用的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等
$server_addr //服务器IP地址
$server_name //服务器的主机名
$server_port //服务器的端口号
$uri //和$document_uri相同
$http_referer //客户端请求时的referer,通俗讲就是该请求是通过哪个链接跳过来的,用curl -e可以指定
Rewrite实战
域名跳转(域名重定向)
示例1(不带条件的):
server{
listen 80;
server_name www.a.com;
root /data/wwwroot/www.a.com;
index index.html;
rewrite /(.*) http://www.b.com/$1 permanent;
}
访问a.com跳转到b.com
[root@jinkai01 vhost]# curl -x127.0.0.1:80 'www.a.com/1.php?a=1&b=2' -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Tue, 22 Sep 2020 13:25:18 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://www.b.com/1.php?a=1&b=2
示例2(带条件的):
server{
listen 80;
server_name www.a.com a.com;
root /data/wwwroot/www.a.com;
index index.html;
if ($host != 'www.a.com')
{
rewrite /(.*) http://www.a.com/$1 permanent;
}
}
通过判断条件,如果$host不等于www.a.com的,跳转到www.a.com
[root@jinkai01 vhost]# curl -x127.0.0.1:80 'www.a.com/1.php?a=1&b=2' -I
HTTP/1.1 404 Not Found
Server: nginx/1.18.0
Date: Tue, 22 Sep 2020 13:27:33 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
[root@jinkai01 vhost]# curl -x127.0.0.1:80 'a.com/1.php?a=1&b=2' -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Tue, 22 Sep 2020 13:27:44 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://www.a.com/1.php?a=1&b=2
示例3(http跳转到https):
server{
listen 80;
server_name www.a.com;
root /data/wwwroot/www.a.com;
index index.html;
rewrite /(.*) https://www.a.com/$1 permanent;
}
[root@jinkai01 vhost]# curl -x127.0.0.1:80 'www.a.com/1.php?a=1&b=2' -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Tue, 22 Sep 2020 13:29:41 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://www.a.com/1.php?a=1&b=2
示例4(域名访问二级目录)
server{
listen 80;
server_name blog.a.com;
index index.html;
rewrite /(.*) http://www.a.com/blog/$1 permanent;
}
[root@jinkai01 vhost]# curl -x127.0.0.1:80 'blog.a.com/1.php?a=1&b=2' -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Tue, 22 Sep 2020 13:31:00 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://www.a.com/blog/1.php?a=1&b=2
示例5(静态请求分离)
server{
listen 80;
server_name www.a.com;
location ~* ^.+.(jpg|jpeg|gif|css|png|js)$
{
rewrite /(.*) http://img.a.com/$1 permanent;
}
}
或者:
server{
listen 80;
server_name www.a.com;
index index.html;
if ( $uri ~* (jpg|jpeg|gif|css|png|js)$)
{
rewrite /(.*) http://img.a.com/$1 permanent;
}
}
[root@jinkai01 vhost]# curl -x127.0.0.1:80 'www.a.com/1.png' -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.18.0
Date: Tue, 22 Sep 2020 13:33:15 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: http://img.a.com/1.png
示例6:防盗链
server{
listen 80;
server_name www.a.com;
location ~* ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$
{
valid_referers none blocked server_names *.a.com a.com *.tobe.com tobe.com;
if ($invalid_referer)
{
rewrite /(.*) http://img.a.com/images/forbidden.png;
}
}
}
说明:这里是通配,跟正则里面的不是一个意思,valid_referers定义白名单,invalid_referers 黑名单,none指的是referer不存在、为空的情况(curl -e 测试), blocked指的是referer头部的值被防火墙或者代理服务器删除或者伪装的情况,该情况下,referer头部的值不以http://或者https://开头(curl -e 后面跟的referer不以http://或者https://开头)。
或者:
location ~* ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$
{
valid_referers none blocked server_names *.a.com *.tobe.com a.com tobe.com;
if ($invalid_referer)
{
return 403;
}
}
[root@jinkai01 vhost]# curl -A "firefox1.1" -e "http://jinkai.com/1.html" -x127.0.0.1:80 'www.a.com/1.png' -I
HTTP/1.1 403 Forbidden
Server: nginx/1.18.0
Date: Tue, 22 Sep 2020 14:01:02 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
[root@jinkai01 vhost]# curl -A "firefox1.1" -e "http://a.com/1.html" -x127.0.0.1:80 'www.a.com/1.png' -I
HTTP/1.1 404 Not Found
Server: nginx/1.18.0
Date: Tue, 22 Sep 2020 14:01:17 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
示例7(discuz伪静态):
location / {
rewrite ^([^.]*)/topic-(.+).html$ $1/portal.php?mod=topic&topic=$2 last;
rewrite ^([^.]*)/forum-(\w+)-([0-9]+).html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last;
rewrite ^([^.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+).html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last;
rewrite ^([^.]*)/group-([0-9]+)-([0-9]+).html$ $1/forum.php?mod=group&fid=$2&page=$3 last;
rewrite ^([^.]*)/space-(username|uid)-(.+).html$ $1/home.php?mod=space&$2=$3 last;
rewrite ^([^.]*)/(fid|tid)-([0-9]+).html$ $1/index.php?action=$2&value=$3 last;
}
示例8:rewrite多个条件的并且
location /{
set $rule 0;
if ($document_uri !~ '^/abc')
{
set $rule "${rule}1";
}
if ($http_user_agent ~* 'ie6|firefox')
{
set $rule "${rule}2";
}
if ($rule = "012")
{
rewrite /(.*) /abc/$1 redirect;
}
}
Nginx的location配置
安装第三方模块echo-nginx-module
安装git:
yum install -y git
克隆源码:
git clone https://github.com/openresty/echo-nginx-module.git
进入nginx源码包目录,清空原先的编译
cd /usr/local/src/nginx-1.18.0
make clean
在原先编译的基础上进行再次编译
nginx -V 查看原先的编译模块
configure arguments: --prefix=/usr/local/nginx --with-http_ssl_module
重新编译
./configure --prefix=/usr/local/nginx --with-http_ssl_module
--add-module=/usr/local/src/echo-nginx-module
make && make install
Location的语法
nginx location语法规则:location [=|~|~*|^~] /uri/ { … }
nginx的location匹配的变量是$uri(请求uri不包含查询字符串,如http://localhost:8080/test?id=10,请求uri是/test)
location = /uri =开头表示精确前缀匹配,只有完全匹配才能生效。
location ^~ /uri ^~开头表示普通字符串匹配上以后不再进行正则匹配。
location ~ pattern ~开头表示区分大小写的正则匹配。
location ~* pattern ~*开头表示不区分大小写的正则匹配。
location /uri 不带任何修饰符,表示前缀匹配。
location / 通用匹配,任何未匹配到其他location的请求都会匹配到。
符号 说明
= 表示精确匹配|
^~ 表示uri以指定字符或字符串开头
~ 表示区分大小写的正则匹配
~* 表示不区分大小写的正则匹配
/ 通用匹配,如果没有其他匹配,任何请求都会匹配到
规则优先级
= 高于 ^~ 高于 ~* 等于 ~ 高于 /
注意:正则匹配会根据匹配顺序,找到第一个匹配的正则表达式后将停止搜索。普通字符串匹配则无视顺序,只会选择最精确的匹配。
规则示例
location = "/12.jpg" { ... }
如:精确匹配开头是12.jpg
www.aminglinux.com/12.jpg 匹配
www.aminglinux.com/abc/12.jpg 不匹配
location ^~ "/abc/" { ... }
如:匹配以/abc/开头的
www.aminglinux.com/abc/123.html 匹配
www.aminglinux.com/a/abc/123.jpg 不匹配
location ~ "png" { ... }
如:匹配区分大小包含png
www.aminglinux.com/aaa/bbb/ccc/123.png 匹配
www.aminglinux.com/aaa/png/123.html 匹配
location ~* "png" { ... }
如:匹配不区分大小写包含png
www.aminglinux.com/aaa/bbb/ccc/123.PNG 匹配
www.aminglinux.com/aaa/png/123.html 匹配
location /admin/ { ... }
如:匹配以admin开头的
www.aminglinux.com/admin/aaa/1.php 匹配
www.aminglinux.com/123/admin/1.php 不匹配
小常识
有些资料上介绍location支持不匹配 !~,
如: location !~ 'png'{ ... }
这是错误的,location不支持 !~
如果有这样的需求,可以通过if来实现,
如: if ($uri !~ 'png') { ... }
注意:location优先级小于if
nginx location优先级
= 高于 ^~ 高于 ~* 等于 ~ 高于 /
对比/和~
示例1:
server{
listen 80;
server_name www.aminglinux.com;
root /tmp/123.com;
location /abc/
{
echo "/";
}
location ~ 'abc'
{
echo "~";
}
}
测试命令:curl -x127.0.0.1:80 'www.aminglinux.com/abc/1.png'
结果是:~
对比~和~*
示例2:
server
{
listen 80;
server_name www.aminglinux.com;
root /tmp/123.com;
location ~ 'abc'
{
echo '~';
}
location ~* 'abc'
{
echo '~*';
}
}
测试命令:curl -x127.0.0.1:80 'www.aminglinux.com/abc/123.html'
结果是:~
示例3:
server
{
listen 80;
server_name www.aminglinux.com;
root /tmp/123.com;
location ~* 'abc'
{
echo '~*';
}
location ~ 'abc'
{
echo '~';
}
}
测试命令:curl -x127.0.0.1:80 'www.aminglinux.com/abc/123.html'
结果是:~*
结论:~和~*优先级其实是一样的,如果两个同时出现,配置文件中哪个location靠前,哪个生效。
对比^~和~
示例4:
server
{
listen 80;
server_name www.aminglinux.com;
root /tmp/123.com;
location ~ '/abc'
{
echo '~';
}
location ^~ '/abc'
{
echo '^~';
}
}
测试命令:curl -x127.0.0.1:80 'www.aminglinux.com/abc/123.html
结果是:^~
对比=和^~
示例5:
server
{
listen 80;
server_name www.aminglinux.com;
root /tmp/123.com;
location ^~ '/abc.html'
{
echo '^~';
}
location = '/abc.html'
{
echo '=';
}
}
测试命令:curl -x127.0.0.1:80 'www.aminglinux.com/abc.html
结果是:=