Firefox: Aria2 RPC 相关改进(bug 修复HTTPS连接中断 + 自定义下载目录)
## 问题描述
### Bug:Firefox 下 Aria2 RPC HTTP 地址发送失败
Firefox 版猫抓中,Aria2 RPC 地址设为 `http://192.168.x.x:6800/jsonrpc` 时,发送提示"发送失败"。
- `http://127.0.0.1:6800/jsonrpc` ✅ 正常
- `http://192.168.x.x:6800/jsonrpc` ❌ 失败
- Chrome 版 ✅ 正常
- 其他 Firefox Aria2 插件调用同一地址 ✅ 正常
### Feature:Aria2 RPC 自定义下载目录
目前 `aria2.addUri` 只传了 `out`(文件名),没有 `dir` 选项。用户无法指定 Aria2 的下载保存路径,只能使用 Aria2 服务端默认目录。建议在设置页添加 Download Path 输入框。
## 环境
- Firefox 151.0.2
- 猫抓 2.6.9
- macOS
## 控制台日志(Bug)
```
Content-Security-Policy:将升级不安全的请求"http://192.168.x.x:6800/jsonrpc"至使用"https"
XHR POST https://192.168.x.x:6800/jsonrpc
NS_ERROR_NET_INTERRUPT
TypeError: NetworkError when attempting to fetch resource.
```
## 根因分析
### Bug 根因
Firefox 对扩展页面(popup、options、background 等)默认施加 `Content-Security-Policy: upgrade-insecure-requests`,将所有 `http://` 请求自动升级为 `https://`。Aria2 RPC 默认不支持 HTTPS,连接中断。
`127.0.0.1`(loopback)被 Firefox 豁免,`192.168.x.x` 无豁免,所以本地正常、远程失败。
### 架构问题
Aria2 RPC 请求 `fetch()` 从 popup 页面直接发起(`js/popup-utils.js:aria2AddUri`),而同类插件通常从 background 发起。现有 `send2local` 功能已经走了 background 消息中转(`js/background.js` line 539),但 Aria2 RPC 没有。
即使 manifest 加了 CSP 去掉 `upgrade-insecure-requests`,Firefox 对 popup 页面的 `fetch()` 仍存在底层限制,必须将请求路由到 background 页面执行。
## 修改方案
### 修改 1(Bug Fix):manifest 添加 CSP
**`manifest.firefox.json`**:
```json
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
}
```
必须是对象格式(Chrome MV3 兼容),字符串格式 Firefox MV3 报错。关键是不包含 `upgrade-insecure-requests`。
### 修改 2(Bug Fix + 架构改进):Aria2 RPC 请求改走 background 中转
#### `js/popup-utils.js`
`aria2AddUri()` 改为 `chrome.runtime.sendMessage`:
```js
function aria2AddUri(data, success, error) {
const msg = {
url: data.url,
requestId: data.requestId,
downFileName: data.downFileName,
requestHeaders: data.requestHeaders,
cookie: data.cookie
};
chrome.runtime.sendMessage({ Message: "aria2AddUri", data: msg }, function (response) {
if (chrome.runtime.lastError) {
error && error(chrome.runtime.lastError);
return;
}
if (response?.error) {
error && error(response.error);
} else {
success && success(response);
}
});
}
```
注意:`data` 包含 DOM 元素(jQuery 对象),直接传会导致 `HTMLDivElement object could not be cloned`,需提取可序列化属性再传。
#### `js/background.js`
在 `chrome.runtime.onMessage.addListener` 内新增 handler:
```js
if (Message.Message == "aria2AddUri") {
const data = Message.data;
const json = {
"jsonrpc": "2.0",
"id": "cat-catch-" + data.requestId,
"method": "aria2.addUri",
"params": []
};
if (G.aria2RpcToken) {
json.params.push("token:" + G.aria2RpcToken);
}
const params = { out: data.downFileName };
if (G.aria2RpcDir) {
params.dir = G.aria2RpcDir;
}
if (G.enableAria2RpcReferer) {
params.header = [];
params.header.push("User-Agent: " + (G.userAgent ? G.userAgent : navigator.userAgent));
if (data.requestHeaders?.referer) {
params.header.push("Referer: " + data.requestHeaders.referer);
}
if (data.cookie) {
params.header.push("Cookie: " + data.cookie);
}
if (data.requestHeaders?.authorization) {
params.header.push("Authorization: " + data.requestHeaders.authorization);
}
}
json.params.push([data.url], params);
fetch(G.aria2Rpc, {
method: "POST",
headers: { "Content-Type": "application/json; charset=utf-8" },
body: JSON.stringify(json)
}).then(response => response.json())
.then(result => sendResponse(result))
.catch(err => sendResponse({ error: err.message || String(err) }));
return true;
}
```
注意 `return true` 保持消息通道异步回调。
### 修改 3(Feature):添加 Download Path 配置
#### `js/init.js`
在 `aria2RpcToken` 后添加默认值:
```js
aria2RpcToken: "",
aria2RpcDir: "",
```
#### `options.html`
在 Aria2 RPC 地址输入框后添加:
```html
<div class="item">
<div>Download Path</div>
<input id="aria2RpcDir" save="input" type="text" class="width100" placeholder="/downloads">
</div>
```
留空则行为不变(Aria2 使用服务端默认目录)。填写后 `aria2.addUri` 请求会带上 `"dir": "用户填的路径"`。
## 兼容性
- 所有改动对 Chrome 版同样兼容
- 修改 2(background 中转)本身是更稳健的架构设计,不依赖 Firefox 特定行为
- 修改 1(CSP)仅 Firefox 需要,Chrome 默认无此限制
1 条评论