共计 4472 个字符,预计需要花费 12 分钟才能阅读完成。
url 重写是指通过配置 conf 文件,以让网站的 url 中达到某种状态时则定向 / 跳转到某个规则,比如常见的伪静态、301 重定向、浏览器定向等
rewrite
语法
在配置文件的 server
块中写,如:
server {rewrite 规则 定向路径 重写类型;}
- 规则:可以是字符串或者正则来表示想匹配的目标 url
- 定向路径:表示匹配到规则后要定向的路径,如果规则里有正则,则可以使用
$index
来表示正则里的捕获分组 - 重写类型:
- last:相当于 Apache 里德 (L) 标记,表示完成 rewrite,浏览器地址栏 URL 地址不变
- break;本条规则匹配完成后,终止匹配,不再匹配后面的规则,浏览器地址栏 URL 地址不变
- redirect:返回 302 临时重定向,浏览器地址会显示跳转后的 URL 地址
- permanent:返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址
简单例子
server {
# 访问 /last.html 的时候,页面内容重写到 /index.html 中
rewrite /last.html /index.html last;
# 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配
rewrite /break.html /index.html break;
# 访问 /redirect.html 的时候,页面直接 302 定向到 /index.html 中
rewrite /redirect.html /index.html redirect;
# 访问 /permanent.html 的时候,页面直接 301 定向到 /index.html 中
rewrite /permanent.html /index.html permanent;
# 把 /html/*.html => /post/*.html,301 定向
rewrite ^/html/(.+?).html$ /post/$1.html permanent;
# 把 /search/key => /search.html?keyword=key
rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
}
last 和 break 的区别
因为 301 和 302 不能简单的只返回状态码,还必须有重定向的 URL,这就是 return 指令无法返回 301,302 的原因了。这里 last 和 break 区别有点难以理解:
- last 一般写在 server 和 if 中,而 break 一般使用在 location 中
- last 不终止重写后的 url 匹配,即新的 url 会再从 server 走一遍匹配流程,而 break 终止重写后的匹配
- break 和 last 都能组织继续执行后面的 rewrite 指令
在 location
里一旦返回 break
则直接生效并停止后续的匹配location
server {
location / {
rewrite /last/ /q.html last;
rewrite /break/ /q.html break;
}
location = /q.html {return 400;}
}
- 访问
/last/
时重写到/q.html
,然后使用新的uri
再匹配,正好匹配到locatoin = /q.html
然后返回了400
- 访问
/break
时重写到/q.html
,由于返回了break
,则直接停止了
if 判断
只是上面的简单重写很多时候满足不了需求,比如需要判断当文件不存在时、当路径包含 xx 时等条件,则需要用到if
语法
if (表达式) {
}
- 当表达式只是一个变量时,如果值为空或任何以 0 开头的字符串都会当做 false
- 直接比较变量和内容时,使用 = 或!=
- ~ 正则表达式匹配,~* 不区分大小写的匹配,!~ 区分大小写的不匹配
一些内置的条件判断:
- - f 和!- f 用来判断是否存在文件
- - d 和!- d 用来判断是否存在目录
- - e 和!- e 用来判断是否存在文件或目录
- - x 和!- x 用来判断文件是否可执行
内置的全局变量
$args:这个变量等于请求行中的参数,同 $query_string
$content_length:请求头中的 Content-length 字段。$content_type:请求头中的 Content-Type 字段。$document_root:当前请求在 root 指令中指定的值。$host:请求主机头字段,否则为服务器名称。$http_user_agent:客户端 agent 信息
$http_cookie:客户端 cookie 信息
$limit_rate:这个变量可以限制连接速率。$request_method:客户端请求的动作,通常为 GET 或 POST。$remote_addr:客户端的 IP 地址。$remote_port:客户端的端口。$remote_user:已经经过 Auth Basic Module 验证的用户名。$request_filename:当前请求的文件路径,由 root 或 alias 指令与 URI 请求生成。$scheme:HTTP 方法(如 http,https)。$server_protocol:请求使用的协议,通常是 HTTP/1.0 或 HTTP/1.1。$server_addr:服务器地址,在完成一次系统调用后可以确定这个值。$server_name:服务器名称。$server_port:请求到达服务器的端口号。$request_uri:包含请求参数的原始 URI,不包含主机名,如:”/foo/bar.php?arg=baz”。$uri:不带请求参数的当前 URI,$uri 不包含主机名,如”/foo/bar.html”。$document_uri:与 $uri 相同。
如:
访问链接是:http://localhost:88/test1/test2/test.php
网站路径是:/var/www/html
$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php
例子
# 如果文件不存在则返回 400
if (!-f $request_filename) {return 400;}
# 如果 host 不是 xuexb.com,则 301 到 xuexb.com 中
if ($host != "xuexb.com"){rewrite ^/(.*)$ https://xuexb.com/$1 permanent;
}
# 如果请求类型不是 POST 则返回 405
if ($request_method = POST) {return 405;}
# 如果参数中有 a=1 则 301 到指定域名
if ($args ~ a=1) {rewrite ^ http://example.com/ permanent;}
在某种场景下可结合 location
规则来使用,如:
# 访问 /test.html 时
location = /test.html {
# 默认值为 xiaowu
set $name xiaowu;
# 如果参数中有 name=xx 则使用该值
if ($args ~* name=(\w+?)(&|$)) {set $name $1;}
# 301
rewrite ^ /$name.html permanent;
}
上面表示:
- /test.html => /xiaowu.html
- /test.html?name=ok => /ok.html?name=ok
location
语法
在 server
块中使用,如:
server {location 表达式 {}
}
location 表达式类型
- 如果直接写一个路径,则匹配该路径下的
- ~ 表示执行一个正则匹配,区分大小写
- ~* 表示执行一个正则匹配,不区分大小写
- ^~ 表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其他 location。
- = 进行普通字符精确匹配。也就是完全匹配。
优先级
- 等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项。
- ^~ 类型表达式。一旦匹配成功,则不再查找其他匹配项。
- 正则表达式类型(~ ~*)的优先级次之。如果有多个 location 的正则能匹配的话,则使用正则表达式最长的那个。
- 常规字符串匹配类型。按前缀匹配。
例子 – 假地址掩饰真地址
server {# 用 xxoo_admin 来掩饰 admin
location / {# 使用 break 拿一旦匹配成功则忽略后续 location
rewrite /xxoo_admin /admin break;
}
# 访问真实地址直接报没权限
location /admin {return 403;
}
}
下面关于 Nginx 的文章您也可能喜欢,不妨参考下:
Nginx 403 forbidden 的解决办法 http://www.linuxidc.com/Linux/2017-08/146084.htm
CentOS 7 下 Nginx 服务器的安装配置 http://www.linuxidc.com/Linux/2017-04/142986.htm
CentOS 上安装 Nginx 服务器实现虚拟主机和域名重定向 http://www.linuxidc.com/Linux/2017-04/142642.htm
CentOS 6.8 安装 LNMP 环境(Linux+Nginx+MySQL+PHP)http://www.linuxidc.com/Linux/2017-04/142880.htm
Linux 下安装 PHP 环境并配置 Nginx 支持 php-fpm 模块 http://www.linuxidc.com/Linux/2017-05/144333.htm
Nginx 服务的 SSL 认证和 htpasswd 认证 http://www.linuxidc.com/Linux/2017-04/142478.htm
Ubuntu 16.04 上启用加密安全的 Nginx Web 服务器 http://www.linuxidc.com/Linux/2017-07/145522.htm
Linux 中安装配置 Nginx 及参数详解 http://www.linuxidc.com/Linux/2017-05/143853.htm
Nginx 日志过滤 使用 ngx_log_if 不记录特定日志 http://www.linuxidc.com/Linux/2014-07/104686.htm
CentOS 7.2 下 Nginx+PHP+MySQL+Memcache 缓存服务器安装配置 http://www.linuxidc.com/Linux/2017-03/142168.htm
CentOS6.9 编译安装 Nginx1.4.7 http://www.linuxidc.com/Linux/2017-06/144473.htm
Nginx 的详细介绍:请点这里
Nginx 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-10/147767.htm