Chrome扩展Fetch API调用中自定义请求头丢失问题排查
问题解决思路
核心问题原因
你在Fetch里加了mode: 'no-cors',这个模式下浏览器会强制限制请求头——只允许用CORS安全请求头(比如Accept、Accept-Language这类),Content-Type: application/json和自定义的X-CLIENT-SECRET都不在安全列表里,所以会被浏览器自动删掉。目标服务器收不到正确的Content-Type,就返回了415错误。
解决方案
既然content.js必须保留,那就把发起请求的逻辑移到background.js里(扩展的service worker拥有更高的网络权限,不受前端CORS限制),content.js只负责触发请求、接收结果就行:
1. 修改Content.js
把原来的Fetch逻辑改成给background发消息:
(() => { chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === 'checkPage') { // 给background发请求指令 chrome.runtime.sendMessage({ action: 'fetchData', url: 'myurl.com', secret: 'mysecret', data: { "randomdata": "data" } }, (response) => { if (response.success) { console.log('Success:', response.data); } else { console.error('Error:', response.error); } }); } }); })();
2. 修改Background.js
新增监听消息的逻辑,负责实际发起请求:
chrome.tabs.onUpdated.addListener((tabId, change, tab) => { if (tab.url.indexOf('website.com/') > -1 && change.status === 'complete') { chrome.tabs.sendMessage(tabId, { action: 'checkPage' }); } }); // 监听content.js的请求消息 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.action === 'fetchData') { fetch(request.url, { method: 'POST', headers: { 'X-CLIENT-SECRET': request.secret, 'Content-Type': 'application/json' }, body: JSON.stringify(request.data) }) .then(response => response.json()) .then(data => { sendResponse({ success: true, data: data }); }) .catch(error => { sendResponse({ success: false, error: error.message }); }); // 必须返回true,告诉Chrome要等异步响应 return true; } });
3. 更新Manifest配置
确保host_permissions包含目标API的域名(比如https://*.myurl.com/*),不然background没法发起请求:
{ "permissions": ["tabs", "activeTab", "scripting", "notifications", "webRequest"], "host_permissions": [ "https://*.website.com/*", "https://*.myurl.com/*" // 添加上目标API的域名 ], "background": { "service_worker": "background.js" }, "content_scripts": [ { "matches": ["https://*.website.com/*"], "js": ["content.js"] } ] }
关键提醒
- 删掉
mode: 'no-cors':background的请求根本不需要这个模式,扩展的service worker不受前端CORS策略限制,只要在host_permissions里声明了目标域名,就能正常发送带自定义头的请求。 - 异步响应要返回true:background里处理Fetch这种异步操作时,必须返回
true,不然Chrome会直接结束消息通道,content.js收不到响应。
内容的提问来源于stack exchange,提问作者Austin Reed
相关产品推荐
相关产品推荐

