Nginx中URL重写功能以及内置变量
1、Nginx内置变量
常见的内置变量有如下几种:
-
$args
,此变量与请求行中的参数相等 -
$query_string
,此变量与$args含义一致。 -
$document_root
,此变量等同于当前请求的root指令指定的值 -
$uri
,表示不带请求参数的当前URL,$uri不包含主机名。如http://www.magedu.net/main/index.do?id=090&partner=search会被定义为/main/index.do -
$document_uri
,此变量与$uri含义一样。 -
$request_uri
#包含请求参数的原始URI,不包含主机名,由客户端请求决定,不能修改。如http://www.magedu.net/main/index.do?id=090&partner=search会被定义为/main/index.do?id=090&partner=search -
$host
,此变量与请求头部中“Host”行指定的值一致。 -
$limit_rate
,此变量用来设置限制连接的速率。 -
$request_method
,#请求资源的方式,GET/PUT/DELETE等 -
$remote_addr
,此变量表示客户端IP地址。 -
$server_addr
#表示请求的服务器地址。 -
$remote_port
,此变量表示客户端端口。 -
$server_port
,此变量表示请求到达的服务器的端口号。 -
$server_name
,此变量表示请求到达的服务器名。默认是localhost -
$remote_user
,此变量等同于用户名,由ngx_http_auth_basic_module认证。 -
$request_filename
,#当前请求的资源文件的路径名称,由root或alias指令与URI请求生成的文件绝对路径,如/apps/nginx/html/main/index.html -
$request_body_file
;#做反向代理时发给后端服务器的本地资源的名称 -
$cookie_name
; #表示key为 name 的cookie值 -
$http_cookie
; #客户端的cookie信息 -
$http_user_agent
; #客户端浏览器的详细信息 -
$scheme
; #请求的协议,如ftp,https,http等 -
$server_protocol
; #请求资源的协议版本,如HTTP/.0,HTTP/.,HTTP/.0等
例1:http://188.19.236.18:8000/abc?test=123&test2=abc :
其中:
$args:test=123&test2=abc
$uri: /abc
$server_addr:188.19.236.18
$server_port:8000
$request_filename:abc
$request_uri:/abc?test=123&test2=abc
例2:http://172.16.213.199:88/test1/test2/test.php ,假定虚拟主机根目录为/var/www/html
其中:
$host:172.16.213.199
$server_port:88
$request_uri: /test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php
2、if指令
if指令用于判断一个条件,如果条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。if指令的使用方法如下:
语法:if (condition) { … }
默认值:none
使用字段:server, location
在默认情况下,if指令默认值为空,可在nginx配置文件的server、location部分使用
另外,if指令可以在判断语句中指定正则表达式或通过nginx内置变量匹配条件等
相关匹配条件如下:
正则表达式匹配规则:
~
表示区分大小写匹配~*
表示不区分大小写匹配!~
和!~*
分别表示区分大小写不匹配及不区分大小写不匹配
文件及目录匹配:
-f
和!-f
用来判断是否存在文件-d
和!-d
用来判断是否存在目录-e
和!-e
用来判断是否存在文件或目录-x
和!-x
用来判断文件是否可执行
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
#先在这个路径下查找
root /data/wwwroot/www.ixdba.net;
if (!-f $request_filrname)
{
#找不到就在这个路径下查找
root /var/www/html/img;
}
if (!-f $request_filrname)
{
#再找不到就到这个路径下查找
root /apps/images;
}
}
location ~ .*.jsp$ {
root /webdata/webapp/www/ROOT;
if (!-f $request_filrname)
{
#再找不到就到这个路径下查找
root /apps/images;
}
#找到了就交给本地的8080端口处理
proxy_pass http://localhost:8080;
}
$ vim /etc/nginx/nginx.conf
location /test {
index index.html;
default_type text/html;
if ( $scheme = http ){
return 301 https://www.hxg.com/; #如果请求协议为http时,范围301,并跳转到https://www.hxg.com/上
}
}
return
return code [text]
; #返回客户端指定的状态码和文本说明
return code URL
; #返回code和新地址
return URL
; #直接返回新地址
停止处理,并返回给客户端指定的响应码(包括: 204, 400, 402 — 406, 408,410, 411, 413, 416, 500 — 504)
并对 301, 302, 303, 307, 308跳转到URL
3、rewrite指令
Nginx通过ngx_http_rewrite_module模块支持url重写、支持if条件判断
但要使用rewrite功能,需要PCRE支持,应在编译nginx时指定PCRE源码目录。
rewrite的使用语法如下:
语法:rewrite regex replacement [flag]
默认值:none
使用字段:server, location, if
其中:
-
regex 正则表达式
-
replacement 跳转的地址
-
flag标记,其支持的flag标记主要有以下几种:
- last, 相当于Apache里的[L]标记,表示完成rewrite之后搜索相应的URI或location。匹配到会继续匹配,直到匹配完。
- break,表示终止匹配, 不再匹配后面的规则。
- redirect,将返回302临时重定向,在浏览器地址栏会显示跳转后的URL地址。
- permanent,将返回301永久重定向,在浏览器地址栏会显示跳转后的URL地址。
其中,last和break用来实现URL重写,浏览器地址栏中的URL地址不变。
重点
如果想实现重写到其他主机而不变浏览器地址栏地址,需要注意
需要结合proxy_pass来实现
location / {
rewrite ^/(.*)$ http://www.tb.cn/$1 break;#这种重写加主机的方式,无论加break还是permanent都无法实现原地址不变
}
#要实现原地址不变跳转,需要结合proxy_pass来实现
location /aaa{
rewrite ^/aaa /abc break;
proxy_pass http://10.50.20.3;
}
下面是一个示例配置,仅列出整个配置中的location部分:
location ~ ^/new/ {
rewrite ^/new/(.*)$ /old/$1 break;#当访问的是/new/开头的链接是重定向到/old下 $1是后项引用,引用的是前面第一个小括号里面的内容
proxy_pass http://www.tb.com;#当上面匹配到了资源,然后交给http://www.tb.com主机处理
}
#在这个例子中
#假定访问的域名是www.newtb.com,那么当访问www.newtb.com/new/web.html时
#nginx可以通过rewrite将页面重定向到www.tb.com/old/web.html
#由于是通过反向代理实现了重定向,因此页面重写后不会引起浏览器地址栏中URL的变化
#这个功能在新旧网站交替的时候非常有用
location /break {
rewrite ^/break/(.*)$ /test/$1 break; #break不会跳转到其他的location
return 666 "break";
}
location /last {
rewrite ^/last/(.*)$ /test/$1 last; #last会跳转到其他的location继续匹配新的URI
return 888 "last";
}
location /abc {
return 666 "return"; #返回状态码666 并直接返回文本return
index index.html;
root /data/nginx;
}
实验
实验:将 http://
请求跳转到 https://
(用rewrite)
$ vim /etc/nginx/nginx.conf
server {
listen 443 ssl; #用listen 跟ssl开启ssl服务
listen 80 ; #同时监听80和443端口
server_name www.abc.com;
root /data/abc; #网站主目录
ssl_certificate /data/ssl/hxg.crt; #指明证书地址
ssl_certificate_key /data/ssl/hxg.key;#指明密钥地址
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
if ($scheme = http ) {#判断,如果是http协议,则跳转到https上
rewrite ^/(.*)$ https://www.abc.com/$1 redirect;
}
}
}
测试:http://www.abc.com --> https://www.abc.com/
实验:当用户访问到公司网站的时输入了一个错误的URL,可以将用户重定向至官网首页
location / {
root /data/abc;
index index.html;
if (!-e $request_filename) {#判断文件是否存在,不存在则执行rewrite
rewrite /(.*) http://www.abc.com/ redirect;
}
}
4、set指令
下面是一个示例配置,仅列出整个配置中的location部分:
location / {
if ($query_string ~ "id=(.*)") {
set $myid $1;
rewrite ^/app.php$ /m-$myid.html?;
}
}
这是一个伪静态的例子
假如访问的域名是 www.abc.com
,那么上面这个配置要实现的功能是将请求为 www.abc.com/app.php?id=100
重定向到 www.abc.com/m-100.html
。
这里用到了if指令和set指令,并且还使用了 $query_string
变量,此变量用于获取请求行中的参数
if指令用来判断请求参数中的id值
然后通过set指令定义了一个变量 $myid
,并将 $query_string
变量中获取到的id值赋给 `$myid
最后通过rewrite指令进行了url重写。
这里需要注意的是:
rewrite只能针对请求的uri进行重写,而对请求参数无能为力,/app.php
问号后面的 id=100
是请求参数,要获取到参数,需要使用nginx的一个内部变量 $query_string
,这样在重写的时候只需把 $query_string
变量追加到重写的uri后面即可,另外,为了防止uri中的参数追加到重写后的uri上,需要在rewrite最后面加个问号。
不加问号演示
location / {
index index.html index.htm;
root html;
if ($query_string ~ "id=(.*)&") {
set $id $1;
rewrite ^/abc.php$ /m-$id.html permanent;
}
}
访问http://10.0.0.5/abc.php?id=123&cc=123 ----------->浏览器地址栏会变成http://10.0.0.5/m-123.html?id=123&cc=123 后面的参数会原封不动的加载后面
加问号演示
location / {
index index.html index.htm;
root html;
if ($query_string ~ "id=(.*)&") {
set $id $1;
rewrite ^/abc.php$ /m-$id.html? permanent;
}
}
访问http://10.0.0.5/abc.php?id=123&cc=123 ----------->浏览器地址栏会变成http://10.0.0.5/m-123.html 后面就不会有参数了
5、break指令
break的用法在前面的介绍中其实已经出现过,它表示完成当前设置的规则后,不再匹配后面的重写规则。break使用语法如下:
语法:break
默认值:none
使用字段:server, location, if
下面是一个应用实例,仅列出整个配置中的server部分:
server {
listen 80;
server_name www.tb.cn;
if ($host != 'www.tb.cn') {
rewrite ^/(.*)$ http://www.tb.cn/error.txt break; #重定向
rewrite ^/(.*)$ http://www.tb.cn/$1 permanent;
}
}
在这个例子中,定义了一个域名www.tb.cn
当访问的域名不是www.tb.cn时,会将请求重定向到“http://www.tb.cn/error.txt” 页面, 由于设置了break指令
因此下面的rewrite规则不再被执行,直接退出
而当访问的域名是www.tb.cn时,将直接执行最后一个rewrite指令。
这里需要重点掌握一下break的功能,它表示完成当前设置的规则后,不再匹配后面的重写规则,也就是当满足if指令后,直接退出,而不会去执行最后一个rewrite指令的规则。
本文来自博客园,作者:厚礼蝎,转载请注明原文链接:https://www.cnblogs.com/guangdelw/p/17911423.html