You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firefox中内容脚本向localhost发送fetch请求被阻止的解决方法

问题描述

我在http://localhost:8081运行了一个简易HTTP服务器,包含GET路由/tts,并返回以下CORS响应头:

self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Access-Control-Allow-Methods", "*")
self.send_header("Access-Control-Allow-Headers", "*")

我编写的WebExtension在https://somedomain.com/*域名上执行内容脚本,脚本中运行:

fetch("http://localhost:8081/tts?text=test").catch(console.error)

但请求既没出现在开发者工具网络面板,也没到达服务器,控制台报错:TypeError: NetworkError when attempting to fetch resource.

manifest文件相关配置如下:

{
    "manifest_version": 2,
    "content_scripts": [{
        "matches": ["https://somedomain.com/*"],
        "js": ["content-script.js"]
    }],
    "permissions": [
        "https://somedomain.com/*",
        "http://localhost:8081/*",
        "http://localhost:8081/tts*",
        "http://localhost:8081/tts/*",
        "http://localhost:8081/tts?*",
        "http://localhost:8081/tts?text=*",
        "tabs"
    ],
    ...
}

已知情况:

  • 服务器运行正常,在somedomain.com控制台手动执行上述fetch请求可正常工作
  • Chrome中测试同一扩展可正常运行,仅Firefox出现问题
  • 从后台脚本发送请求也能正常工作,仅Firefox内容脚本中请求失败

解决方案

1. 修改Firefox本地扩展访问配置

Firefox默认限制内容脚本访问本地资源(包括localhost),需手动开启权限:

  • 打开Firefox的about:config页面
  • 搜索配置项extensions.webextensions.localhost_access
  • 将该选项的值改为true

修改后重启浏览器,内容脚本的fetch请求即可正常发送到本地服务器。

2. 简化Manifest权限配置

Manifest中不需要重复添加多个localhost相关权限,保留"http://localhost:8081/*"即可,其余冗余权限可删除,简化后的权限配置如下:

"permissions": [
    "https://somedomain.com/*",
    "http://localhost:8081/*",
    "tabs"
],

3. 备选方案:通过后台脚本转发请求

如果不想修改浏览器全局配置,可借助后台脚本中转请求(后台脚本不受Firefox本地资源访问限制):

内容脚本代码

// 向后台脚本发送请求消息
browser.runtime.sendMessage({
    type: "fetchTTS",
    text: "test"
}).then(response => {
    console.log("请求结果:", response);
}).catch(console.error);

后台脚本代码

// 监听内容脚本的消息
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.type === "fetchTTS") {
        // 后台脚本执行fetch请求
        fetch(`http://localhost:8081/tts?text=${encodeURIComponent(message.text)}`)
            .then(res => res.text()) // 根据服务器返回格式选择res.json()或res.text()
            .then(data => sendResponse(data))
            .catch(err => sendResponse({ error: err.message }));
        return true; // 标记为异步响应,避免消息通道提前关闭
    }
});

内容的提问来源于stack exchange,提问作者Forivin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:20:23