当前位置: 首页 > news >正文

【Nginx12】Nginx学习:HTTP核心模块(九)浏览器缓存与try_files

Nginx学习:HTTP核心模块(九)浏览器缓存与try_files

浏览器缓存在 Nginx 的 HTTP 核心模块中其实只有两个简单的配置,这一块也是 HTTP 的基础知识。之前我们就一直在强调,学习 Nginx 需要的就是各种网络相关的基础知识,其中更重要的就是 HTTP 和 TCP 相关的内容。另外一个 try_files 配置指令也是 Nginx 中非常常用的一个指令,用于找不到指定的路径文件时,可以去按顺序查找备用的一些文件路径,非常实用。

浏览器缓存

在 HTTP 协议中,有许多和浏览器缓存有关的选项,而在 Nginx 的核心配置中,也有两个与之相关的配置。

if_modified_since

if_modified_since 是由浏览器发送的,让服务端来判断返回 200 还是 304 ,在 Nginx 中,它用于指定响应的修改时间与 if_modified_since 请求头的比较方法。

if_modified_since off | exact | before;

默认值是 exact ,每个选项分别代表:

  • off 忽略 “If-Modified-Since” 请求头 (0.7.34)

  • exact 精确匹配

  • before 响应的修改时间小于等于 “If-Modified-Since” 请求头指定的时间

etag

etag 是由服务器端生成的,客户端通过发送 If-Match 或者 If-None-Match 这个条件判断请求来验证资源是否修改。Nginx 中,这个配置可以开启或关闭为静态文件自动计算 “ETag” 响应头。

etag on | off;

它的默认值是 on 。

测试

正常情况下,我们第一次打开某个静态页面,是没有 if_modified_since 的,服务端会返回 ETag 和 Last-Modified 以及 200 状态码。

81e22c4e25260e5a61b809e047343324.png

然后第二次请求的时候,浏览器就会带上 if_modified_since ,服务端会返回 304 表示使用本地缓存就可以了。

05306e894d83893664f6356a0670986c.png

这是在默认情况下。现在我们修改 Nginx 的配置,先将 if_modified_since 设置为 off ,然后强刷页面之后再进行普通刷新 ,会发现不管是强刷还是普通刷新,响应头和请求虽然没有什么变化,但服务端都只会返回 200 了。也就是说,服务端不会去比较浏览器发送过来的 if_modified_since 值来判断是否返回 304 。

接下来测试 etag ,这个就麻烦一点,首先,我们要将 if_modified_since 设置为 before ,意思就是访问的静态资源文件的修改时间小于当前浏览器提供的 If-Modified-Since 时,才返回 200 。这样的话,如果我们手动修改文件的时间,将时间修改到当前时间之后很长的一段时间,那么就可以让浏览器在非强刷的状态下一直返回 304 。

touch -m -d "2023-09-08 12:23:04" /usr/local/nginx/html/aaa.html

默认 etag 为 on 的情况下,你再次修改文件的时间,依然会正常返回一次 200 。这就是 etag 的作用,它是根据文件一些属性进行综合 Hash 从而返回一个值,客户端保存上回的 etag 值后传送到服务端进行比对。而如果现在你将 etag 设置为 off 的话,那么再次请求就不会有 Etag 响应头返回了,这时修改文件的时间,甚至是修改文件的内容(注意修改内容后还要手动修改一下文件的修改时间,否则 if_modified_since 就会生效返回 200 了),后面的请求也将一直会是 304 (非强刷)。

ps.浏览器强刷其实就是浏览器不带任何和 HTTP 缓存有关的请求头进行一次请求访问。

Etag 最主要解决的其实是 if_modified_since 的一些缺点,比如说有些时候可能我们只是周期性地修改一下文件,但文件内容不发生变化(只是文件修改时间变动),这时其实可以不用重新 200 响应的。另外还有 if_modified_since 只支持到秒级,而 Etag 的 Hash 变化是跟随文件变动的,因此它的粒度更细一些。还有一种情况就是某些服务器不能精确的得到文件的最后修改时间,这也会导致 if_modified_since 产生问题,更典型的就是客户端时间和服务器时间不同步,比如有的人的电脑可能时间一直就是错的。

这一块的内容是 HTTP 的基础知识,而且写文字也不太好描述怎么测试,大家可以关注下后期的视频哈,在视频中咱们再好好演示。

try_files

按指定顺序检查文件是否存在,并且使用第一个找到的文件来处理请求,那么处理过程就是在当前上下文环境中进行的。

try_files file ... uri;
try_files file ... =code;

其实就是我们不确定用户访问的路径或者文件存不存在,这时可以按照 try_files 指定的顺序来展示指定的 URI ,通常它都会和 $uri 变量一起搭配使用,$uri 变量就是当前访问的 location 地址。说白了,就是给请求的链接准备好备胎,能够为用户带来更优良的用户体验。

文件路径是根据 root 指令和 alias 指令,将 file 参数拼接而成。 可以在名字尾部添加斜线以检查目录是否存在,比如“$uri/”。 如果找不到任何文件,将按最后一个参数指定的uri进行内部跳转。 比如:

location /tf1/ {try_files $uri /50x.php;
}

现在试试访问 /tf1 ,会发现显示的是 50x.php 的内容,如果 /tf1 下面有页面的话,那么直接访问就可以查看到指定的页面。这种感觉是不是有点像 error_page ,其实上面的内容就相当于是下面这样的代码。

location /tf1/ {error_page 404 /50x.php;
}

$uri 变量表示的是规范以后的 URI ,也就是拼接请求之后完整的 URI 路径。不过这个变量的值可能会随着请求的处理过程而改变,比如,当进行内部跳转时,或者使用默认页文件时。

这下就看出来了吧,try_files 按顺序,如果第一个 $uri 找到文件了,就直接使用这个文件,如果没找到,就找第二个,依次类推,我们也可以一直向后多写几个 uri ,直到有一个能够找到对应的文件。

location /tf2/ {try_files $uri /tf2/1.html /tf2/2.html;
}

在 tf2 目录下,建立了两个文件,然后访问 /tf2 ,会显示 1.html 的内容,访问 /tf2/2.html ,正常显示 2.html 的内容,按顺序来说 $uri 是第一位的,后面的顺序哪个先找到就按哪个来。因此,除了指定访问 /tf2/2.html 之外,其它链接都会打开 1.html (如果有 404 的 error_page 设置,则直接走 404 的)。那么如果是跳转 uri 呢?比如我们跳转到 php 的 URI 上。

location /tf3/ {try_files $uri /50x.php /404.php;
}

随便访问 /tf3 或者目录中的任意不存在的路径,我这里会弹出下载,查看请求 Content-Type 会变成 application/octet-stream ,下载的文件是 php 的源码。注意,这里是个坑点,不要在静态配置中进行这样的 try_files 。换成带 PHP 相关配置的再试试。

location /tf4/ {try_files $uri /tf4/1.php /1.php =404;fastcgi_pass unix:/var/sock/php-fpm/www.sock;fastcgi_index  index.php;fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;include        fastcgi_params;
}

现在访问 /tf4 会显示到最外面那个我们之前测试的时候打印所有 $_SERVER 内容的 1.php 页面。如果我们创建 tf4 目录,并且添加一个 1.php ,并打印 echo "this is tf4/1.php."; 那么,再次刷新,页面就会展示 this is tf4/1.php. 。这样才能正常的显示 php 。不过我们直接用静态配置去 try_files 动态文件也有别的方法,就是使用命名 location 。

location /tf5/ {try_files $uri @tf5php;
}
location @tf5php {root html;fastcgi_pass unix:/var/sock/php-fpm/www.sock;fastcgi_index  index.php;fastcgi_param  SCRIPT_FILENAME  $document_root/tf5php/index.php;include        fastcgi_params;
}

访问 /tf5 或者 /tf5/xxx.html ,都会打开 tf5php 目录下的 index.php 文件。注意,这里演示的是从 静态 文件到 php 文件,如果是 /tf5/xxx.php 则会被之前我们配置过的 ~ \.php 的配置拿走,不会走到这边来。

我们再来看看响应码的问题。

location /tf6/ {try_files $uri $uri/ /xxx.html  =401;
}

这一段表示的是如果前面 uri... 部分都没有匹配到,那么就会返回 401 的状态码。大家可以自己试一下访问 /tf6 下的任意文件,最后返回的都是 401 状态。

好了,我们再来看一下 Laravel 文档中给的一个 Nginx 配置,其中有一段内容是大部分 PHP 应用在部署的时候也都会要求写上的。

location / {try_files $uri $uri/ /index.php?$query_string;}

在全局的 location 中,访问 uri 页面或者 uri/ 目录,找不到文件的话,会转给 /index.php,并且把请求行的 GET 参数转给 /index.php 文件。通常现代化的框架都是单一入口,index.php 总是可以接收请求的,如果确实还是找不到,也将由 PHP 应用来进行对应的 404 或者 500 处理。

另外,try_files 还可以做一件非常常见的事,就是显示默认图片。

location /images/ {try_files $uri /images/default.gif;
}

正常的图片路径找不到图片了,就使用默认的图片来代替,这也是很多网站的基本需求。

总结

今天的内容不难吧,加起来就是三个配置项,不过我们做了很多的测试。缓存对于现代化的 Web 开发来说非常重要,而 HTTP 缓存则是最前端的面向客户一级的缓存。对于静态资源来说,有着非常重要的作用,可以大大减少服务器的压力。而 try_files 的灵活则为我们带来了更多的特色功能,类似于默认图片这类的配置都能够非常简单方便。

不过估计大家平常可能对这几个指令用得也并不多,毕竟缓存那两个都有默认值,我们保持默认就好了。而 try_files 通常最多的就是用在上文所说的全局路径的处理上,是使用 Laravel 时必备的一个配置。但是,通过今天的学习,相信咱们将来在需要的时候,也能马上想起来这些配置指令的用法,能够更加灵活自如的运用它们。学习,就是这样一步一步的不断积累,一次一次的不停实践。

参考文档:

http://nginx.org/en/docs/http/ngx_http_core_module.html

相关文章:

【Nginx12】Nginx学习:HTTP核心模块(九)浏览器缓存与try_files

Nginx学习:HTTP核心模块(九)浏览器缓存与try_files 浏览器缓存在 Nginx 的 HTTP 核心模块中其实只有两个简单的配置,这一块也是 HTTP 的基础知识。之前我们就一直在强调,学习 Nginx 需要的就是各种网络相关的基础知识&…...

【1】-Locust性能测试工具介绍与安装

Locust介绍 locust是一个开源的压测工具,其官网地址是Locust - A modern load testing framework,通过编写Python代码,可以轻松实现百万级的并发,相对于我们熟悉的Jmeter来说,其对压测机的要求更低,而且使…...

基于拉格朗日-遗传算法的最优分布式能源DG选址与定容(Matlab代码实现)

目录 1 概述 2 数学模型 2.1 问题表述 2.2 DG的最佳位置和容量(解析法) 2.3 使用 GA 进行最佳功率因数确定和 DG 分配 3 仿真结果与讨论 3.1 33 节点测试配电系统的仿真 3.2 69 节点测试配电系统仿真 4 结论 1 概述 为了使系统网损达到最低值&a…...

【已解决】jupyter notebook里已经安装了第三方库,还是提示导入失败

在jupyter notebook中运行Python代码,明明已经安装了第三方库,还是提示导入失败。 以导入pandas库为例,其他库同理: 报错代码: import pandas报错原因: 电脑上存在多个python运行环境(比如&a…...

Mybatis使用collection映射一对多查询分页问题

场景&#xff1a;页面展示列表&#xff0c;需要查询多的字段&#xff0c;和一的字段。并且还要分页。 这时候直接想到的是手写sql。 /*** 标签*/private List<BasicResidentTags> tags;Data TableName("basic_resident_tags") public class BasicResidentTag…...

Linux/Windows路由管理

本文主要介绍如果通过linux/Windows命令添加IPV6地址&#xff0c;查看添加IPV6默认路由&#xff0c;查看IPV6邻居缓存 一、Linux 1、查看地址 IPV4: route netstat -route ip route IPV6: ip -6 route show route -A inet6 route -62、添加IPV6地址 ip -6 addr add <…...

openpnp - 设备矫正的零碎记录

文章目录 openpnp - 设备矫正的零碎记录概述笔记设备内部不能有任何强干扰源相机就选100W像素的就行, 没有特殊要求openpnp软件的选择视觉归位必须禁止轴的赤隙矫正不用做运行openpnp软件的计算机, 必须是台式机校验完成后, 数据占用的体积END openpnp - 设备矫正的零碎记录 概…...

Linux内核中的链表、红黑树和KFIFO

lLinux内核代码中广泛使用了链表、红黑树和KFIFO。 一、 链表 linux内核代码大量使用了链表这种数据结构。链表是在解决数组不能动态扩展这个缺陷而产生的一种数据结构。链表所包含的元素可以动态创建并插入和删除。链表的每个元素都是离散存放的&#xff0c;因此不需要占用连…...

【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动

[导读]本系列博文内容链接如下&#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 在【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值一文中介绍了如何利用…...

Android 设备兼容性使用(详细版)

经典好文推荐,通过阅读本文,您将收获以下知识点: 一、设备兼容性分类 二、硬件设备兼容 三、软件 APP 兼容 四、兼容不同语言 五、兼容不同分辨率 六、兼容不同屏幕方向布局 七、兼容不同硬件 Feature 八、兼容不同SDK平台 一、设备兼容性分类 Android设计用于运行在许多不同…...

React 中的常见 API 和生命周期函数

目录 useStateuseEffectuseRefdangerouslySetInnerHTML生命周期函数 constructorcomponentDidMountstatic getDerivedStateFromPropsshouldComponentUpdatecomponentDidUpdatecomponentWillUnmount useState useState 是 React 的一个 Hook&#xff0c;用于在函数组件中添加…...

神经网络中遇到的 python 函数(Pytorch)

1.getattr() 函数用于返回一个对象属性值。 def getattr(object, name, defaultNone): # known special case of getattr"""getattr(object, name[, default]) -> valueGet a named attribute from an object; getattr(x, y) is equivalent to x.y.When a …...

分布式事务及解决方案

1、分布式事务 分布式事务就是在一个交易中各个服务之间的相互调用必须要同时成功或者同时失败&#xff0c;保持一致性和可靠性。在单体项目架构中&#xff0c;在多数据源的情况下也会发生 分布式事务问题。本质上来说&#xff0c;分布式事务就是为了保证不同数据库的数据一致性…...

【宏定义】——编译时校验

文章目录 编译时校验功能描述代码实现示例代码正常编译示例编译错误示例预处理之后的结果 代码解析!!estruct {int:-!!(e); }sizeof(struct {int:-!!(e); }) 参考代码 编译时校验 功能描述 用于在编译时检查一个条件是否为真&#xff0c;如果条件为真则会编译失败&#xff0c…...

C#学习系列之System.Windows.Data Error: 40报错

C#学习系列之System.Windows.Data Error: 40报错 前言报错内容解决总结 前言 在用户界面使用上&#xff0c;代码运行没有问题&#xff0c;但是后台报错&#xff0c;仔细研究了报错内容&#xff0c;解决问题&#xff0c;所以记录一下。 报错内容 System.Windows.Data Error: 4…...

【java安全】RMI

文章目录 【java安全】RMI前言RMI的组成RMI实现Server0x01 编写一个远程接口0x02 实现该远程接口0x03 Registry注册远程对象 Client 小疑问RMI攻击 【java安全】RMI 前言 RMI全称为&#xff1a;Remote Method Invocation 远程方法调用&#xff0c;是java独立的一种机制。 RM…...

rcu链表综合实践

基础知识 rcu-read copy update的缩写。和读写锁起到相同的效果。据说牛逼一点。对于我们普通程序员&#xff0c;要先学会使用&#xff0c;再探究其内部原理。 链表的数据结构&#xff1a; struct list_head {struct list_head *next, *prev; };还有一种&#xff1a;struct h…...

odoo16-python框架-动作

总结 1 模型和视图的 设计之美 view_ids, view_id,view_mode 最终目的都是为了生成views, 也就是视图. 模型是死的,像男人,一成不变 视图像女人,千变万化, 姿态万千 一阴一阳之谓道,设计之美又在这里得到了体现 2 所有的动作都可以通过web界面来配置 可以通过在"设…...

微信小程序——同一控件的点击与长按事件共存的解决方案

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

selenium自动化-获取元素属性信息

在写自动化过程中我们会想验证自己的代码是否正确&#xff0c;比如登录之后&#xff0c;通过用户名或其他信息来证明你登录成功&#xff0c;或者点击链接后&#xff0c;是否会跳转新的页面。通过获取元素属性信息&#xff0c;可以解决我们的疑惑。 一、获取内容对象的内容信息 …...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...