Service Worker 可通过 fetch 事件拦截请求并用 new Request() 动态改写 headers,需克隆原始 headers 后 set/append 字段,跳过删除项,显式设置 credentials;禁用修改 Forbidden header,注意 body 类型与 CORS 限制。

Service Worker 可以在 fetch 事件中拦截 fetch 请求,并通过构造新的 Request 对象来动态改写请求头(Headers),但必须注意:原始 request.headers 是只读的,无法直接修改,只能“替换”而非“编辑”。
改写 Headers 的核心步骤
关键在于用 new Request(url, options) 创建新请求实例,并在 options.headers 中传入更新后的头信息。常见操作包括添加、覆盖或删除特定 header:
- 先调用
new Headers(request.headers)克隆原始头,避免直接操作只读对象 - 使用
headers.set()覆盖已有字段(如Authorization),或headers.append()追加新字段(如X-Client-Version) - 若需移除某个 header,不能用
delete(Headers 接口不支持),而应跳过它——即不将其写入新 headers 实例 - 对于带凭据的请求(如 cookie),必须显式设置
credentials: request.credentials,否则会被重置为'omit'
实际代码示例
以下是在 Service Worker 中拦截所有同源 API 请求,并注入版本号与设备标识的典型写法:
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// 仅处理同源 /api/ 开头的 fetch 请求
if (url.origin === location.origin && url.pathname.startsWith('/api/')) {
const originalHeaders = new Headers(event.request.headers);
const newHeaders = new Headers(originalHeaders);
// 动态注入字段(可结合 localStorage 或 client 状态)
newHeaders.set('X-Client-Version', '2.1.0');
newHeaders.set('X-Device-Type', 'web');
// 构造新 Request,保留 method、body、credentials 等关键属性
const modifiedRequest = new Request(event.request.url, {
method: event.request.method,
headers: newHeaders,
body: event.request.body,
credentials: event.request.credentials,
redirect: event.request.redirect,
referrer: event.request.referrer,
referrerPolicy: event.request.referrerPolicy,
mode: event.request.mode,
cache: event.request.cache,
integrity: event.request.integrity
});
event.respondWith(fetch(modifiedRequest));
return;
}
});
需要注意的关键限制
某些 header 浏览器禁止 Service Worker 修改,即使你设了也不会生效(例如 Host、Content-Length、Connection 等“Forbidden header names”)。此外:
- POST/PUT 请求若含
body,必须确保新 Request 的body类型与原始一致(如FormData、JSON.stringify后的字符串等),否则可能被丢弃或报错 - 不能在
fetch事件中 await 异步操作后再构造 Request(如等 localStorage 读取),因为 event 是同步触发的;如需异步数据,建议提前在 install 阶段缓存,或用clients.matchAll()主动通信获取 - 修改后的请求仍受 CORS 策略约束,添加自定义 header 不会绕过服务端的
Access-Control-Allow-Headers检查
调试建议
打开 Chrome DevTools → Application → Service Workers,勾选 “Update on reload” 和 “Offline”,再刷新页面。可在 fetch 回调中加 console.log(newHeaders.get('X-Client-Version')) 验证是否注入成功;同时在 Network 面板查看请求头是否真实出现在发出的请求中(注意:部分 header 如 X-* 在面板中默认折叠,需点击“Headers”右侧箭头展开)。

















