coo*_*ool 40 etag cache-control if-modified-since express
Expressjs自动发送etags.我想知道如何生成etag ..它是基于get例程动态生成的内容.或者我是否可以通过生成内容(动态内容 - 来自DB)并将etag作为相同的内容进行过程来对其进行维护.
可能是一个中间件,它只是检查它是否是有效的会话ID并传回客户端提供的相同etag,或者可能是基于url +会话ID ...这将是唯一的方式.并结束请求,而不是通过整个数据库调用和所有这些东西.在这种情况下,我需要知道客户端正在拨打304电话.
我可以使用expires标签.但是当会话结束时.如果有人打开网址,它不应该允许.所以我认为etag也应该基于会话ID.如何修改可以在此动态内容方案中工作.它可以用吗?
ste*_*iot 42
在撰写本文时(2014年7月8日),使用CRC32(源)生成弱ETag,并使用MD5(源)生成强ETag .
根据Express的一个贡献者所说,您可以通过以下方式指定是使用强或弱ETag:
app.enable('etag') // use strong etags
app.set('etag', 'strong') // same
app.set('etag', 'weak') // weak etags
Run Code Online (Sandbox Code Playgroud)
看起来您也可以指定自己的自定义函数来执行ETag,如下所示:
app.set('etag', function(body, encoding){ /* return valid etag */ });
Run Code Online (Sandbox Code Playgroud)
故宫包新鲜也是值得看的,因为它是在快递用于新鲜度检查(来源1,源2).
至于您的应用程序,请记住您可以res.set('etag', 'my-awesome-etag-value')在调用res.send()(或类似函数)之前覆盖任何响应头.可以在此处找到进一步的讨论(包括优点和缺点):https://github.com/visionmedia/express/issues/2129#issue-34053148
让我在 2021 年用更新的信息和代码链接来解释它。
这是一个相对直接和简单(没有火箭科学)的概念,但同时也是一件非常棘手的事情,作为一名开发人员,在它咬你之前你应该真正了解它!
因此, Etag (根据Wikipedia/Etag)是一个 HTTP 标头。
它可以在 DevTools中一些GET调用的“响应头”部分看到,如下面的屏幕截图。
在 Express 中,它可以以W/(weak, default ) 或 not (strong)开头,然后是<LEN>-<VALUE>,其中 VALUE 是 27 个字符长,LEN 是 VALUE 的长度,以十六进制表示。(2021 年 6 月的源代码)
啊,好问题。答案是:缓存!
(PS。并且只缓存客户端和服务器之间的网络流量。这是响应数据的传输,通过 HTTP(S) 发送到客户端;不是服务器到数据库的任何类型的内部缓存或其他什么。 )
机制比较简单。
假设客户端(浏览器,如 Chrome)调用https://myserver.com/user/profile/get端点并获取当前用户所有个人资料数据的大型 JSON 响应(例如,姓名、电话、照片 URL 等 30 个字段,等等,等等)。除了将响应作为 JSON 对象传递给您的应用程序之外,客户端在其自己的私有内部网络层中还会将此数据存储在{'https://myserver.com/users/profile/get': <this-json-response-object> }.
现在,下一次(甚至几天和会话之后)客户端将要调用 的相同端点.../user/profile/get,它可以告诉服务器“嘿,我的缓存中有这个 <previous_json_from_the_cache>,所以不要发送如果你要发送的正是这个,那就结束了。 ”
这是!
问题是,如果客户端从缓存中发送整个 JSON 对象,在对服务器的请求中,这既存在安全风险,而且效率很低——同样的 30 字段 JSON 对象通过网络发送,甚至可能两次!
这里发生的事情是,客户端(即 Chrome 浏览器)可以计算一个哈希值(比如 MD5,它既不可逆又更短),并在第二个请求中说“嘿,如果你要发送的 JSON 的 MD5 哈希值我回来的是这个<computed_hash>,我已经有了!别送过去了。 ”
现在,发生的事情是,服务器将像以前一样计算响应(从 DB 和所有内容中提取)。但是,仅在发送响应数据之前,它会计算响应的哈希值(在服务器端)以查看它是否与客户端所说的匹配。如果是这样,它会发送 304 HTTP 状态响应代码,而不是 200,这意味着“没有任何变化”。
好吧,在上面的例子中,如果你密切注意,哈希计算在客户端和服务器端都发生。至少,改变算法会很困难。因此,实际上,“响应的哈希”实际上也是第一次在服务器端计算,并将发送回客户端。
此计算出的“当前的响应”,这回来与响应的散列是在ETag所述的头响应。
这样,每当客户端收到响应时,它都会将:存储{ ".../profile/get": [<ETag>, <JSON-Response-Data>] }在其内部缓存中。
然后,在未来的任何请求中,客户端都会将此ETag值发送到服务器(在某些标头中,例如if-none-match),以暗示如果新调用的响应将具有ETagthis ,则它可以接收 304 。
所以,回顾一下:
ETag value 并不是什么疯狂的事情,而是响应数据(主体)的不可逆、短且快速的散列值。ETag在对客户端的响应中发送标头。if-none-matched标头(其值是先前Etag从服务器接收的值)。默认情况下,它发生在 Express.js 中。所以,坐下来享受吧!
您不太可能需要弄乱其设置。
啊! 欢迎来到我的生活。:D 这就是我来到这里并进行所有这些研究的方式。
快递包使用的ETAG包(它只是一个文件,由同一人管理)来产生ETag值。在内部,该etag包使用 sha1加密的主体,并没有什么疯狂的,以保持最佳性能。(如果你想象一下,这个函数会被很多!至少或每一次平均两次的任何服务器接收和处理GET调用。)
为了决定它应该执行 304 还是 200,当客户说“我的缓存中已经有了这些值”时,Express 使用新包(同样只有一个文件,实际上只有一个返回布尔值的函数,由同一个人维护) )。在内部,fresh包读取if-none-matched请求标头 ( reqHeaders['if-none-match']) 的标记,并将其与即将发出etag的响应 ( resHeaders['etag']) 的标记进行比较。
当您的架构以及客户端和服务器之间的通信依赖于自定义标头时,就会出现问题!
例如,您想在任何请求上更新身份验证或会话令牌,并在后台刷新它并发送一个新令牌,作为某些请求的响应头。
当前 Etag 实现的 Express,仅依赖于响应体,而不是响应头。 甚至,他们允许放置的自定义函数(doc,code)只获取正文内容,而不是响应头。
所以,发生的情况是,当响应(例如配置文件数据)未更改时,您的客户端可能会重用过时的身份验证令牌并由于身份验证/会话标签无效而将用户踢出!
您可以这样app.set("etag", false);做 Express 停止发送它。根据这个答案,您还可以/应该使用nocache viaapp.use(nocache())来发送“不要打扰自己缓存它!” 从服务器到客户端的标头。
干杯!
| 归档时间: |
|
| 查看次数: |
22517 次 |
| 最近记录: |