Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 157 题:浏览器缓存 ETag 里的值是怎么生成的 #383

Open
yygmind opened this issue May 15, 2020 · 3 comments
Open

第 157 题:浏览器缓存 ETag 里的值是怎么生成的 #383

yygmind opened this issue May 15, 2020 · 3 comments

Comments

@yygmind
Copy link
Contributor

yygmind commented May 15, 2020

No description provided.

@Undo101
Copy link

Undo101 commented May 15, 2020

Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)。
语法:

ETag: W/"<etag_value>"
ETag: "<etag_value>"

'W/'(大小写敏感)
表示使用弱验证器,可选。 弱验证器很容易生成,但不利于比较。 强验证器是比较的理想选择,但很难有效地生成。 相同资源的两个弱Etag值可能语义等同,但不是每个字节都相同。
"<etag_value>"
实体标签唯一地表示所请求的资源。 它们是位于双引号之间的ASCII字符串(如“675af34563dc-tr34”)。 没有明确指定生成ETag值的方法。 通常,使用内容的散列,最后修改时间戳的哈希值,或简单地使用版本号。 例如,MDN使用wiki内容的十六进制数字的哈希值。

@trexguo
Copy link

trexguo commented May 15, 2020

1. Nginx 的 ETag 生成方式:http://lxr.nginx.org/source/src/http/ngx_http_core_module.c

注意:行1608、1609

1581 ngx_int_t
1582 ngx_http_set_etag(ngx_http_request_t *r)
1583 {
1584     ngx_table_elt_t           *etag;
1585     ngx_http_core_loc_conf_t  *clcf;
1586 
1587     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1588 
1589     if (!clcf->etag) {
1590         return NGX_OK;
1591     }
1592 
1593     etag = ngx_list_push(&r->headers_out.headers);
1594     if (etag == NULL) {
1595         return NGX_ERROR;
1596     }
1597 
1598     etag->hash = 1;
1599     ngx_str_set(&etag->key, "ETag");
1600 
1601     etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3);
1602     if (etag->value.data == NULL) {
1603         etag->hash = 0;
1604         return NGX_ERROR;
1605     }
1606 
1607     etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
1608                                   r->headers_out.last_modified_time,
1609                                   r->headers_out.content_length_n)
1610                       - etag->value.data;
1611 
1612     r->headers_out.etag = etag;
1613 
1614     return NGX_OK;
1615 }

2. Apache 的生成方式 http://httpd.apache.org/docs/2.2/mod/core.html#fileetag

关于配置里提到的 inode,不知道的可以参考:http://www.ruanyifeng.com/blog/2011/12/inode.html


不同 Web 服务器或者 CDN 的 ETag 生成方式可能不一样。

@WangYingYaTou
Copy link

Etag 是一个文件变换就要重新生成的一个值,如果用hash来计算达不到效率
不过http也没有明确指出它的计算方式吧
不过在nginx里面,是由Last-Modified和content-length的十六进制组合而成
这样想来是个Etag加强版本的Last-Modified,毕竟Last-Modified是个时间戳,只能精确到秒

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants