nginx伪静态之try_files和rewrite讲解

一、伪静态是个啥?

 

1、说起伪静态基本上搞web开发的人,多多少少都有了解与使用,有人会说什么时候会使用伪静态?使用原生的url地址不是蛮好的吗,确实是这样的,其实我蛮喜欢原生的url风格的,但是由于某些原因我不得不使用伪静态。

比如:

(1), url地址比较友好,看着爽,更有说服务力

(2), 如果是一个内容站,有利于seo优化

(3), 有效的防止sql注入,让别人不知道你真实的url地址

(4), 比如你在公司上班,你的领导,可能就会让你设置伪静态,工作需要。

 

2、那说了好处,有没有坏处呢? 坏处肯定是有的,与原生的url比较在性能上,不如原生的url,简单的说伪静态就是在服务器上又进行了一层url解析,消耗服务器资源。当然了这点消耗与优点相比,我们还是可以接受的。

 

3、那伪静态长什么样呢?

比如:

http://www.xxab.com/hello/world.html

http://www.xxx.com/content/23223.html

http://www.xxx.com/content/go/cb

以上这样的url地址,我们就可以叫伪静态url(都是进行过url处理)

 

4、那原生的url地址是什么样呢?

比如:

http://www.xxx.com/index.php?name=will&age=20

http://www.xxx.com/content/list.php?id=3

以上这样的url地址,就是原生url

 

 

 

二、nginx怎么设置伪静态呢?

 

如果你之前使用过apache的话很简单的,只要apache有rewrite模块就可以了,然后就可以自己编写rewrite规则了。

但是nginx如果你不明白原理就麻烦了,但只要明白原理就简单的,下面的案例都是我本地开发环境的配置,如果讲的不太合适的地方,请见谅。

 

 

1,nginx配置:

server {

        listen       80;

        server_name  localhost;

        access_log  logs/localhost.access.log  main;

        #开启伪静态日志,方便调试

        rewrite_log on;

        #输出错误日志,错误级别设置为notice

        error_log logs/error-test.log notice;

 

 

        root html/test;

        index  index.php index.html;

        location / {

                try_files $uri $uri/ @aaaaab;

        }

 

        //注意使用@符号,不然不成功

        location @aaaaab {

                include D:/nginx/html/test/.htaccess;

        }

 

        location ~ \.php$ {

                fastcgi_pass 127.0.0.1:9000;

                fastcgi_index index.php;

                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

                 include fastcgi_params;

        }

}

 

 

2, .htaccess清单

 

rewrite 语法格式:

rewrite   [regex]                  [replacement]      [flag];

               url正则表达式        替换真实url          标记(last,break)

 

实例:

rewrite   ^/article/index.html$   /index.php?process=article&a=index last;

 

//注意,这是一行,由于一行写不下,自动换行了

rewrite ^/article/list/([0-9]+)-([0-9]+)-([0-9]+).html$ 

/index.php?process=article&a=list&group_id=$1&category_id=$2&p=$3 last;

 

rewrite ^/article/detail/([0-9]+).html$   /detail.php?id=$1 last;

 

rewrite ^/group/([0-9]+).html$   /group.php?group_id=$1 last;

 

 

 

3,上面的案例虽然小,但是五脏俱全,我们开始一个一个的分析

 

try_files $uri $uri/ @aaaaab; 这句话是什么意思?

 

try_files从字面上理解就是尝试文件,再结合环境理解就是“尝试读取文件”,那他想读取什么文件呢,

答:读取静态文件

 

$uri  这个是nginx的一个变量,存放着用户访问的地址,

比如:http://www.xxx.com/index.html, 那么$uri就是 /index.html

 

$uri/ 代表访问的是一个目录,比如:http://www.xxx.com/hello/test/    ,那么$uri/就是 /hello/test/

 

完整的解释就是:try_files 去尝试到网站目录读取用户访问的文件,如果第一个变量存在,就直接返回;

不存在继续读取第二个变量,如果存在,直接返回;不存在直接跳转到第三个参数上。

 

 

比如用户访问这个网地址:http://www.xxx.com/test.html

try_files首先会判断他是文件,还是一个目录,结果发现他是文件,与第一个参数 $uri变量匹配。

然后去到网站目录下去查找test.html文件是否存在,如果存在直接读取返回。如果不存在直接跳转到第三个参数,而第三个参数是一个location,而这个location里面配置的就是rewrite规则。

 

 

说到这里大家就明白了,能看懂上面的配置了。

那有人会问了,还要try_files干什么呀,直接使用rewrite不就可以了吗?

答:不可以,因为rewrite这个指令把所有请求过来的url地址,都与htaccess文件中的正则地址进行一次匹配,这样的话,静态的url地址也进行了一次匹配,比如http://xxxx.com/aa.png,这个地址是不需要重写的,但是rewrite也进行了一次匹配,这就浪费服务器资源,影响执行效率。而我们真正需要匹配的,其实都是一些动态url地址,如果我说这么多,你还不明白的话,可以打印日志查看。

 

 

include D:/nginx/html/test/.htaccess; 这句就是去加载伪静态文件,把所有的规则写在这里面,注意这里要使用全路径,不然不成功。

<think>我们正在讨论Nginx的`try_files`指令的高级用法常见陷阱。结合用户提供的引用之前的对话历史,我们可以总结如下:###高级用法1.**多级回退机制**[^4]```nginxlocation/{try_files$uri$uri//static/$uri/fallback.html=404;}```-按顺序检查:原始URI→目录形式→`/static/`目录下的相同文件→备用页面→返回404状态码-特别适合静态资源版本化管理(如引用[4]场景)2.**命名位置跳转**[^3]```nginxlocation/uploads/{try_files$uri@app;}location@app{proxy_passhttp://backend;#可添加额外代理头proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;}```-当文件不存在时跳转到代理处理-避免暴露后端服务器路径3.**与`error_page`联动**```nginxlocation/protected/{try_files$uri$uri/@auth;}location@auth{error_page401=@login;auth_request/auth-check;...}```-文件检查失败时触发认证流程4.**正则位置块中的智能回退**```nginxlocation~*\.(jpg|png)${try_files/cdn-cache$uri$uri@origin;}location@origin{proxy_passhttp://image-server;proxy_cachemy_cache;}```-优先从CDN路径查找,不存在则回源获取###常见陷阱及解决方案1.**路径泄露风险**[^1]-错误配置:```nginxserver{root/etc/nginx;#危险!将根目录设为配置目录location/{try_files$uri$uri/=404;}}```-攻击者可能通过`GET/nginx.conf`获取敏感配置-**解决方案**:```nginx#限定作用范围location/conf/{denyall;#禁止访问配置目录}#或使用安全根目录root/var/www/safe;```2.**目录遍历漏洞**-当使用`try_files$uri/...`时,若目录不存在:```nginxlocation/reports/{try_files$uri/=404;#$uri/会尝试列出目录}```-若关闭`autoindex`仍可能返回403,但配置不当会暴露目录结构-**解决方案**:```nginxautoindexoff;#全局关闭目录列表location/reports/{try_files$uri$uri/index.html=404;#不检查目录}```3.**循环重定向**-错误示例:```nginxlocation/{try_files$uri$uri/@backend;}location@backend{rewrite^/index.php?route=$uri;#重写后再次进入try_files}```-导致无限循环(日志中出现多次302/301)-**解决方案**:```nginxlocation@backend{proxy_passhttp://php-backend$uri?$args;#直接代理,避免重写回原路径}```4.**尾部斜杠处理不一致**-现象:-访问`/blog`返回200,`/blog/`却返回404-原因:```nginxlocation/blog{try_files$uri$uri//index.html;}```-`$uri/`要求物理存在`/blog//`目录(双斜杠)-**解决方案**:```nginxlocation/blog{#显式指定目录路径try_files$uri$uri/blog/index.html/index.html;}```5.**性能损耗**-深层级检查:```nginxtry_files$uri/cache/$uri@backend;```-当`/cache/`是网络挂载点时,文件检查可能成为性能瓶颈-**优化方案**:```nginxmap$uri$cached_file{default'';~^(?<path>/img/.*\.jpg)$/nfs/cache$path;#仅对特定路径启用}location/{try_files$uri$cached_file@backend;}```###最佳实践总结|**场景**|**推荐配置模式**|**优势**||----------|------------------|----------||SPA应用路由|`try_files$uri$uri//index.html;`|支持前端路由||多版本静态资源|`try_files/v2/$uri/v1/$uri$uri;`|无缝版本切换||代理应用入口|`try_files$uri@proxy_backend;`|安全隔离||访问控制|`try_files''@auth;`|强制认证|>**调试提示**:使用`strace`跟踪Nginx工作进程的文件访问:>```bash>sudostrace-p$(pgrep-f'nginx:worker'|head-1)-etrace=file>```§§相关问题§§1.Nginx的`location`匹配优先级规则在实际配置中如何应用?2.如何利用Nginx的`map`指令实现动态配置?3.Nginx反向代理中如何正确处理WebSocket连接?</think>### Nginx `try_files` 指令高级用法及常见陷阱 #### 一、核心功能解析 `try_files` 用于按顺序检查文件/目录是否存在,若均不存在则执行备用操作: ```nginx try_files $uri $uri/ /fallback.html =404; ``` - **检查顺序**: 1. `$uri`(原始请求文件) 2. `$uri/`(目录索引) 3. `/fallback.html`(备用文件) 4. `=404`(返回404状态码) --- #### 二、高级用法场景 ##### 1. SPA应用路由处理(单页应用) ```nginx location / { try_files $uri $uri/ /index.html; } ``` - **作用**:所有路由请求均返回`index.html`,由前端框架处理路由[^4] - **场景**:Vue/React等前端框架部署 ##### 2. 多版本静态资源优先级 ```nginx location / { try_files /static/$uri $uri =404; } ``` - **逻辑**:优先使用`/static/`目录下的文件,不存在则用根目录文件[^4] - **示例**: `http://example.com/logo.png` → 先检查 `/static/logo.png` → 不存在则用 `/logo.png` ##### 3. 动态代理回退 ```nginx location /uploads/ { try_files $uri @backend_proxy; } location @backend_proxy { proxy_pass http://app_server; proxy_set_header Host $host; } ``` - **流程**:文件不存在时自动转发到后端应用[^3] ##### 4. 安全隔离配置 ```nginx location /conf/ { try_files "" @block_access; # 禁止直接访问配置目录 } location @block_access { return 403 "Access Denied"; } ``` - **防护**:防止通过`GET /nginx.conf`泄露敏感配置[^1] ##### 5. 条件式错误处理 ```nginx location / { try_files $uri @fallback; } location @fallback { error_page 404 = @dynamic_handler; return 404; # 触发自定义404处理 } location @dynamic_handler { proxy_pass http://php_fpm; } ``` --- #### 三、常见陷阱及解决方案 ##### 陷阱1:目录遍历风险 ```nginx # 危险配置(暴露目录结构) location /reports/ { try_files $uri $uri/ =404; } ``` - **风险**:当`autoindex on`时,访问`/reports/`会列出目录内容[^1] - **修复**: ```nginx autoindex off; # 全局关闭目录列表 location /reports/ { try_files $uri $uri/index.html =404; } ``` ##### 陷阱2:尾部斜杠处理不一致 ```nginx location /blog { try_files $uri $uri/ /index.html; } ``` - **问题**: `/blog` 返回200 ✅ `/blog/` 返回404 ❌(因`$uri/`要求物理目录存在) - **修复**: ```nginx location /blog { try_files $uri $uri/blog/index.html /index.html; } ``` ##### 陷阱3:代理循环 ```nginx location @backend { rewrite ^ /index.php?route=$uri; # 重写后再次进入try_files } ``` - **现象**:日志中出现多次302重定向 - **修复**: ```nginx location @backend { proxy_pass http://backend$uri?$args; # 直接代理 } ``` ##### 陷阱4:性能损耗 ```nginx try_files $uri /nfs_mounted/$uri @backend; ``` - **问题**:网络存储(如NFS)的`stat()`检查成为瓶颈 - **优化**: ```nginx map $uri $use_nfs { ~^/images/ 1; # 仅对/images/启用 } location / { try_files $uri @nfs_check @backend; } location @nfs_check { if ($use_nfs) { try_files /nfs_mounted/$uri @backend; } return 404; } ``` ##### 陷阱5:变量未转义 ```nginx try_files /cache/$uri @backend; ``` - **风险**:若`$uri`含`../`可能越权访问 - **修复**: ```nginx location / { set $safe_uri $uri; if ($uri ~ "\.\.") { return 403; } try_files /cache/$safe_uri @backend; } ``` --- #### 四、最佳实践建议 1. **路径规范** ```nginx # 使用root而非alias避免混淆 location /static/ { root /var/www; # 完整路径:/var/www/static/ } ``` 2. **错误处理隔离** ```nginx error_page 404 /404.html; location = /404.html { internal; # 禁止外部直接访问 root /etc/nginx/error_pages; } ``` 3. **调试技巧** ```bash # 跟踪文件检查过程 sudo strace -p $(pgrep nginx) -e trace=file ``` > **关键原则**: > - 避免在`try_files`中使用`if`判断(易引发意外行为)[^2] > - 所有备用路径必须物理存在 > - 敏感目录显式禁止访问[^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值