正文ETag(实体标签)是 HTTP 条件请求的核心。强 ETag 适用于字节级一致性判断,弱 ETag 适用于语义一致但字节可能不同的场景(例如:相同数据经不同格式化)。本文给出强/弱 ETag 的生成与 `If-None-Match`、`If-Modified-Since` 的协同治理实践。

一、强/弱 ETag 生成方法// app/api/etag/route.ts

export const runtime = 'edge'

async function strongETag(input: ArrayBuffer) {

const digest = await crypto.subtle.digest('SHA-256', input)

const bytes = new Uint8Array(digest)

let b64 = ''

for (let i = 0; i < bytes.length; i++) b64 += String.fromCharCode(bytes[i])

return '"sha256-' + btoa(b64) + '"'

}

function weakETag(size: number, mtimeMs: number) {

return `W/"${size}-${mtimeMs}"`

}

二、条件请求与 304 响应治理优先使用 ETag 校验,其次使用 `Last-Modified` 与 `If-Modified-Since`。始终在 304 响应中回显当前的标准化响应头(ETag/Last-Modified/Cache-Control),确保中间缓存层的一致性。export async function GET(req: Request) {

// 示例资源:真实场景可来自存储/渲染结果

const body = new TextEncoder().encode('Hello ETag v2')

const lastModified = new Date('2025-11-01T00:00:00Z')

const strong = await strongETag(body.buffer)

const weak = weakETag(body.byteLength, lastModified.getTime())

const inm = req.headers.get('if-none-match') || ''

const ims = req.headers.get('if-modified-since')

// 优先 ETag 校验;兼容强/弱标签

if (inm && (inm.includes(strong) || inm.includes(weak))) {

return new Response(null, {

status: 304,

headers: {

ETag: strong,

'Last-Modified': lastModified.toUTCString(),

'Cache-Control': 'public, max-age=60, s-maxage=300, must-revalidate'

}

})

}

// 次选 Last-Modified 校验

if (ims) {

const imsDate = new Date(ims)

if (!Number.isNaN(imsDate.getTime()) && imsDate.getTime() >= lastModified.getTime()) {

return new Response(null, {

status: 304,

headers: {

ETag: strong,

'Last-Modified': lastModified.toUTCString(),

'Cache-Control': 'public, max-age=60, s-maxage=300, must-revalidate'

}

})

}

}

// 命中失败:返回资源与标准缓存头

return new Response(body, {

headers: {

'Content-Type': 'text/plain; charset=utf-8',

ETag: strong,

'Last-Modified': lastModified.toUTCString(),

'Cache-Control': 'public, max-age=60, s-maxage=300, stale-while-revalidate=600',

'Vary': 'Accept-Encoding'

}

})

}

三、选型建议与注意事项强 ETag:适合静态资源、经过完整哈希的产物(如构建输出),确保字节级一致。弱 ETag:适合语义一致但字节可能不同的场景(JSON 序列化差异、空白字符变化),提高命中率但不用于 Range 请求合并。回显策略:在 304 响应中始终回显当前 ETag 与 Last-Modified,避免中间层状态偏差。`Vary` 管理:仅在必要的协商维度(如 `Accept-Encoding`、`Accept`、UA-CH)设置 `Vary`,防止缓存分片过度导致命中率下降。安全与一致性:为动态生成内容设置合理的 `max-age/s-maxage` 与 `must-revalidate`/`stale-while-revalidate`,避免过时内容长尾污染。

四、扩展:HEAD 与弱标签策略对于目录索引或列表页,可提供 `HEAD` 路由快速探测并返回 ETag/Cache-Control,不携带响应体,降低探测带宽与耗时。弱标签可用于允许“轻微变更但视为未变”场景,需结合业务语义评估适配度。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部