首页
其他
Action
Another action
Something else here
游客
登录系统
16
46小时前
小四
是不是只有我死了 是不是只有我死了 是不是只有我死了 是不是只有我死了 是不是只有我死了
25小时前
二愣子
呵呵
昨天
查看所有消息
16
46小时前
小四
是不是只有我死了 是不是只有我死了 是不是只有我死了 是不是只有我死了 是不是只有我死了
25小时前
二愣子
呵呵
昨天
查看所有消息
16
46小时前
小四
是不是只有我死了 是不是只有我死了 是不是只有我死了 是不是只有我死了 是不是只有我死了
25小时前
二愣子
呵呵
昨天
查看所有消息
发布创作
nginx配置rewrite的用法详解
超级管理员
|
662
|
2019-11-26
### 1. rewrite在if中的用法 ``` if (条件判断) { 具体的rewrite规则 } ``` if条件判断语句由Nginx内置变量、逻辑判断符号和目标字符串三部分组成。 其中,内置变量是Nginx固定的非自定义的变量,如 | 变量 | 说明 | | ------------ | ------------ | | $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相同。| 逻辑判断符号,有 | 变量 | 说明 | | ------------ | ------------ | | = | 进行普通字符精确匹配。也就是完全匹配 | | ! | 非 | | != | 不等于 | | ~ | 表示执行一个正则匹配,区分大小写 | | ~* | 表示执行一个正则匹配,不区分大小写 | | !~ | 不匹配 | | !~* | 不区分大小写不匹配 | | -f`和`!-f` | 用来判断是否存在文件 | | -d`和`!-d` | 用来判断是否存在目录 | | -e`和`!-e` | 用来判断是否存在文件或目录 | | -`x和`!-x` | 用来判断文件是否可执行 | 优先级 1. location = 2. location 完整路径 3. location ^~ 路径 4. location ~, ~* 5. locaiton 部分起始路径 6. locaiton / #### 示例 当http请求方法为post时,返回403状态码 ``` if ($request_method = POST) { return 403; } ``` 通过浏览器标识匹配关键字,禁止IE浏览器访问 ``` if ($http_user_agent ~* MSIE) { return 403; } ``` 限制多个浏览器 ``` if ($http_user_agent ~* "MSIE|firefox|Chrome") { return 403; } ``` 当请求的文件不存在时,进行重定向或return状态码等处理操作 ``` if(!-f $request_filename) { rewrite 语句; } ``` 判断uri中某个参数的内容 ``` # \d表示数字,{6,8}表示数字出现的次数是6到8次,当uri中gid参数的值包含6-8个数字那么执行rewrite语句 if($request_uri ~* 'gid=\d{6,8}/') { rewrite 语句; } ``` ### 2. rewrite中break和last的用法 1. break和last在location{}外部时 ``` server{ listen 80; server_name test.com; root /home/www/test.com; # 请求1.html文件时,会被重定向到2.html,然后被重定向到3.html,最后返回的文件为3.html rewrite /1.html /2.html; rewrite /2.html /3.html; } ``` 在rewrite 指令后面添加break ``` server{ listen 80; server_name test.com; root /data/wwwroot/test.com; # 请求1.html文件时,会被重定向到2.html,然后直接返回2.html,break在此处的作用就是当匹配第一个rewrite指令成功时,不执行后面的rewrite指令 rewrite /1.html /2.html break; # 不执行 rewrite /2.html /3.html; } ``` 当break后面还有location{}的情况 ``` server{ listen 80; server_name test.com; root /data/wwwroot/test.com; # 请求1.html文件时,会返回403状态码 # 当1.html被重定向到2.html时,break不会匹配后面的rewrite规则,但条件2.html匹配location{}定义的文件2.html,所以会执行return 403 rewrite /1.html /2.html break; # 不执行 rewrite /2.html /3.html; # 会执行 location /2.html { return 403; } } ``` 2. break和last在location{}内部时 ``` server{ listen 80; server_name test.com; root /data/wwwroot/test.com; # 请求1.html时,会经过两次重定向到3.html,3.html又刚好匹配location /3.html{},所以返回b.html # 请求2.html时,会直接返回a.html,因为location /2.html {} 更精准,优先匹配 location / { rewrite /1.html /2.html; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; } } ``` 在rewrite后面添加break ``` server{ listen 80; server_name test.com; root /data/wwwroot/test.com; # 请求1.html,会返回2.html,不会返回a.html,当break再location {} 内部时,遇到break后,当前location{} 以及后面的location{} 的指令都不再执行 location / { rewrite /1.html /2.html break; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; } } ``` 在rewrite后面添加last ``` server{ listen 80; server_name test.com; root /data/wwwroot/test.com; # 请求1.html时,会返回a.html,在location {} 内部遇到last,当前location {}中剩下的指令不会再执行,但被重定向的url会重新匹配一遍location {} location / { rewrite /1.html /2.html last; rewrite /2.html /3.html; } location /2.html { rewrite /2.html /a.html; } location /3.html { rewrite /3.html /b.html; } } ``` #### `break` 和 `last` 用法总结 1. 当rewrite规则在location{}外,break和last作用一样,遇到break或last后,其后续的rewrite/return语句不再执行。但后续有location{}的话,还会近一步执行location{}里面的语句,前提是请求能匹配该location 2. 当rewrite规则在location{}里,遇到break后,本location{}与其他location{}的所有rewrite/return规则都不再执行 3. 当rewrite规则在location{}里,遇到last后,本location{}里后续rewrite/return规则不执行,但重写后的url再次从头匹配所有location ### 3. return的用法 该指令一般用于对请求的客户端直接返回响应状态码。在该作用域内return后面的所有nginx配置都是无效的,可以使用在server、location以及if配置中,除了支持跟状态码,还可以跟字符串或者url链接。 直接返回状态码 ``` server{ listen 80; server_name www.test.com; # 访问时,直接返回403状态码,return返回内容后,后面的配置rewrite不会执行 return 403; rewrite www.test.net; } ``` 当return在if 判断中时 ``` server { ..... # 请求的文件包含.password或.bak时,直接返回404,rewrite不会执行,但if {}外的配置会继续执行,return只在当前作用域中生效 if ($request_uri ~ "\.password|\.bak") { return 404; rewrite /(.*) /index.html; } ..... } ``` 返回字符串 ``` server{ listen 80; server_name www.test.com; # 返回字符串必须加上状态码,否则会报错 return 200 "hello"; } ``` 返回nginx变量 ``` location /1.html { return 200 "$host $request_uri"; } ``` 返回url ``` server{ listen 80; server_name www.test.com; # 返回url时,必须以http://或https://开头 return http://www.test.com/index2.html; } ``` 返回html代码 ``` if ($http_referer ~ 'baidu.com') { # 注意:return http://$host$request_uri; 在浏览器中会提示"重定向的次数过多" return 200 ""; } ``` ### 4. rewrite的语法规则 ``` rewrite regex replacement [flag] ``` flag标志位 | 变量 | 说明 | | ------------ | ------------ | | last | 相当于Apache的[L]标记,表示完成rewrite | | break | 停止执行当前虚拟主机的后续rewrite指令集 | | redirect | 返回302临时重定向,地址栏会显示跳转后的地址 | | permanent | 返回301永久重定向,地址栏会显示跳转后的地址 | 域名跳转 ``` location / { # # .*为正则表达式,表示uri,用()括起来,在后面的uri中可以调用它,第一次出现的()用$1调用,第二次出现的()用$2调用,以此类推。 rewrite /(.*) http://www.test.com/$1 permanent; } ``` 域名跳转的第二种写法 ``` location / { rewrite /.* http://www.test.com$request_uri permanent; } ``` 文件跳转 ``` server{ listen 80; server_name www.test.com; root /data/wwwroot/test.com; index index.html; if ($request_uri !~ '^/web/') { # 将uri请求的文件重定向到web/目录中去寻找 rewrite /(.*) /web/$1 redirect; } } ``` 域名跳转(域名重定向)- 单个域名 ``` server{ listen 80; server_name www.test.com; rewrite /(.*) http://www.test.net/$1 permanent; } ``` 域名跳转(域名重定向)- 多个域名 ``` server{ listen 80; server_name www.test.com www.test.net; if ($host != 'www.test.net') { rewrite /(.*) http://www.test.net/$1 permanent; } } ``` http跳转https ``` server{ listen 80; server_name www.test.com; rewrite /(.*) https://www.test.com/$1 permanent; } ``` 跳转二级目录 ``` server{ listen 80; server_name bbs.test.com; rewrite /(.*) http://www.test.com/bbs/$1 last; } ``` 动静态请求分离 ```server{ listen 80; server_name www.test.com; location ~* .*\.(jpg|jpeg|gif|css|png|js)$ { # #假设www.test.com的服务器在国外,访问速度较慢,img.test.com的服务器在国内,访问速度正常,可以将访问www.test.com静态文件的请求重定向到img.test.com,提高文件返回速度 rewrite /(.*) http://img.test.com/$1 permanent; } } ``` 第二种写法 ``` server{ listen 80; server_name www.test.com; if ( $uri ~* 'jpg|jpeg|gif|css|png|js$') { rewrite /(.*) http://img.test.com/$1 permanent; } } ``` ### 5. 防盗链配置 ``` server{ listen 80; server_name www.test.com; # 配置防盗链避免别的网站引用www.test.com不想被引用的图片等文件 location ~* ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$ { valid_referers none blocked server_names *.test.com if ($invalid_referer) { return 403; } } } ``` | 变量 | 说明 | | ------------ | ------------ | | http_referer | 表示从哪儿点击进网站的,比如从百度搜索引擎访问的 | | valid_referers | 白名单 | | invalid_referer | 无效的(未在白名单中定义的) | | none | 允许referer为空(也就是允许直接访问,未从其他站点跳转的请求) | | blocked | 允许来源地址不含http/https | ### 6. 伪静态(将静态页面重写为动态) ``` # 示例为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; } ``` ### 7. 多个if并用 ``` location /{ #nginx配置文件语法不支持if嵌套,需要通过多个if并用判断时,使用标识变量值的方式处理 # 补充:shell中可以直接写 set $a “$a1” ,$a的值会变为01,nginx中需要将变量名用{}标识:set $a “${a}1” set $a 0; if ($document_uri !~ '^/abc') { set $a "${a}1"; #uri不以/abc开头时,$a的值变为01 } if ($http_user_agent ~* 'ie6|firefox') { set $a "${a}2"; #浏览器标识包含ie6或者Firefox时,$a的值变为012 } if ($a = "012") #当满足前两个if判断时,重写url { rewrite /(.*) /abc/$1 redirect; } } ```
一克字符 | EchoStr
互联网 ICP 备案:粤ICP备2024297332号
站长邮箱: echostr@163.com