在前端开发中,我们经常会使用到后端接口来获取数据或者进行其他操作。而在使用 Express 框架时,经常会遇到调用 app.get() 返回 304 Not Modified 的问题。这个问题看起来非常简单,但是背后涉及到的知识点却非常多。本文将详细介绍这个问题及其解决方法。
问题描述
假设我们有一个网站,需要从后端获取一些数据。我们使用 Express 框架来搭建后端,并在后端定义了如下的路由:
app.get('/api/data', (req, res) => { const data = { name: 'John', age: 18 }; res.json(data); });
在前端代码中,我们使用 axios 请求这个接口,代码如下:
axios.get('/api/data').then(response => console.log(response.data));
我们希望每次请求都能获取到最新的数据,但是实际上在多次请求后发现,每次获取到的数据都是相同的。通过查看 Chrome 开发者工具,发现控制台返回的状态码一直是 304 Not Modified。
问题原因
在 HTTP 协议中,如果客户端通过浏览器访问一个网站,并在浏览器中保存了这个网站的缓存,那么在下次访问时,浏览器会自动从缓存中获取数据,而不是直接从服务器请求。这个过程就称为 HTTP 缓存。
当客户端发送一个带有 If-None-Match 和 If-Modified-Since 头信息的请求到服务器,服务器会自动比较客户端提供的 ETag 以及 If-Modified-Since 和服务器上的版本号及修改时间,如果相同则服务器会返回 304 Not Modified,客户端会从缓存中获取数据,这样就能节省带宽和服务器资源,提高访问速度。
在 Express 中,如果我们没有正确配置缓存,就会导致每次请求都返回 304 Not Modified,从而出现上述问题。
解决方法
1. 指定 Cache-Control
我们可以通过设置 Response Headers 中的 Cache-Control 头信息来指定缓存的类型以及过期时间。Cache-Control 可以设置以下几个值:
- public:可以被任何一个方向缓存,包括浏览器以及中间代理服务器;
- private:只能被浏览器缓存,不能被中间代理服务器缓存;
- no-cache:不能被任何方向缓存,需要重新从服务器获取;
- max-age:指定缓存的有效期,单位为秒。
我们可以通过如下代码来设置 Cache-Control:
app.get('/api/data', (req, res) => { const data = { name: 'John', age: 18 }; res.header('Cache-Control', 'max-age=0, private, no-cache, no-store, must-revalidate'); res.json(data); });
2. 指定 ETag
在我们的 Response Headers 中可以指定 ETag 和 Last-Modified 头信息。ETag 是一个字符串,表示当前版本的资源。当客户端请求时,服务器会返回当前资源的 ETag,客户端会在请求头信息中发送 If-None-Match 字段,服务器会比较两个值是否一致,如果一致,则返回 304 Not Modified。如果我们没有设置 ETag 或者 ETag 不正确,就会导致每次请求都返回 200 OK。
我们可以通过如下代码来设置 ETag:
-- -------------------- ---- ------- -------------------- ----- ---- -- - ----- ---- - - ----- ------- ---- -- -- ----- ---- - ------------------------------------------------------------------------------- ------------------ ------ --------------- ---
3. 指定 Last-Modified
Last-Modified 表示资源最后一次修改的时间,当客户端访问时,服务器会将这个时间和客户端提供的 If-Modified-Since 字段进行比较,如果一致,则返回 304 Not Modified。和 ETag 一样,如果我们没有设置 Last-Modified 或者 Last-Modified 不正确,就会导致每次请求都返回 200 OK。
我们可以通过如下代码来设置 Last-Modified:
app.get('/api/data', (req, res) => { const data = { name: 'John', age: 18 }; res.header('Last-Modified', new Date().toUTCString()); res.json(data); });
示例代码
下面是一个使用 ETag 的完整示例代码:
-- -------------------- ---- ------- ----- ------- - ------------------- ----- --- - ---------- ----- ---- - ----- -------------------- ----- ---- -- - ----- ---- - - ----- ------- ---- -- -- ----- ---- - ------------------------------------------------------------------------------- --------------------------- ------------ ------------------ ------ --------------- --- ---------------- -- -- -------------------- --- --------- -- ---- ------------
总结
通过本文的介绍,我们了解了调用 app.get() 一直返回 304 Not Modified 的原因以及解决方法。为了避免这个问题,我们需要正确设置缓存的类型、过期时间、ETag 和 Last-Modified 头信息。在重要的接口上,可以使用 ETag 和 Last-Modified 来进行缓存,可以有效减少网络传输时间,提高性能。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/646d7b2b968c7c53b0c27252