Electron Referrer 对象详解:用 url 与 policy 字段精确控制 Referer 行为
本文基于 Electron 官方 API 文档中的 Referrer Object 结构定义,系统讲解该对象的 url、policy 两个字段,逐一解释 8 种 Referrer-Policy 取值的含义,并结合 Electron C++ 源码中的字符串到 net::ReferrerPolicy 枚举的映射实现、loadURL 的 httpReferrer 参数解析链路,帮助你在主进程、<webview>、net 请求等场景中精确控制请求的 Referer 头。
什么是 Referrer 对象
Referrer 是 Electron API 中的一个数据结构(structure),而不是可直接实例化的类。它成对描述一次导航或请求所使用的 HTTP Referrer(即浏览器侧的 Referer 请求头来源):
urlstring — HTTP Referrer URL,即作为来源页的完整 URL;policystring — Referrer-Policy 策略值,决定url在跨源、降级(如https请求http)等场景下以何种粒度(完整 URL / 仅源 / 不发送)出现在Referer请求头中。
policy 的合法取值为:default、unsafe-url、no-referrer-when-downgrade、no-referrer、origin、strict-origin-when-cross-origin、same-origin、strict-origin。
与纯字符串形式的 referrer 相比,Referrer 对象的关键价值在于:它把"来源 URL"和"发送策略"绑定在一起。只传一个 URL 字符串时,策略只能走默认值;而传入 Referrer 对象后,Electron 会按你指定的策略在每次真实发出 Referer 头之前做裁剪。
8 种 policy 取值含义速查
| 取值 | 行为摘要 |
|---|---|
default |
使用默认策略(不额外裁剪) |
unsafe-url |
始终发送完整 URL,即使从 https 降级到 http 也照常发送 |
no-referrer-when-downgrade |
同源或 https 升 https 时发送完整 URL;降级时不发送 |
no-referrer |
永不发送 Referer 头 |
origin |
只发送来源的源(scheme + host + port),不发送路径 |
strict-origin-when-cross-origin |
同源请求发送完整 URL;跨源只发送源;降级请求不发送 |
same-origin |
仅同源请求发送完整 URL,跨源不发送 |
strict-origin |
只发送源,且仅在安全上下文(如 https 到 https)下发送 |
其中"降级"(downgrade)指从安全协议(https)转向非安全协议(http)的导航,这也是多数 strict-* / no-referrer-when-downgrade 策略的核心判断条件。
源码实现:JS 字符串到 net::ReferrerPolicy 的映射
Electron 在 V8 与 Chromium 网络栈之间通过 gin 的 Converter 完成字符串到枚举的转换。在 electron_api_url_loader.cc 中可以看到完整的映射表:
template <>
struct Converter<net::ReferrerPolicy> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
net::ReferrerPolicy* out) {
using Val = net::ReferrerPolicy;
static constexpr auto Lookup =
base::MakeFixedFlatMap<std::string_view, Val>({
{"", Val::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN},
{"no-referrer", Val::NO_REFERRER},
{"no-referrer-when-downgrade", Val::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE},
{"origin", Val::ORIGIN},
{"origin-when-cross-origin", Val::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN},
{"same-origin", Val::CLEAR_ON_TRANSITION_CROSS_ORIGIN},
{"strict-origin", Val::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE},
{"strict-origin-when-cross-origin", Val::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN},
{"unsafe-url", Val::NEVER_CLEAR},
});
return FromV8WithLowerLookup(isolate, val, Lookup, out);
}
};
从这段实现可以得到几个与文档对照后值得注意的事实:
strict-origin-when-cross-origin与空字符串""映射到同一枚举REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN。也就是说 Chromium 的默认策略等价于strict-origin-when-cross-origin,文档中列出的default语义在实现层面落到这一默认值上。- 映射表额外接受
origin-when-cross-origin,即源码侧支持的策略字符串比 Referrer 文档 列出的 8 个还多一个;文档中的 8 个取值是面向Referrer结构policy字段的正式声明。 FromV8WithLowerLookup表明匹配是大小写不敏感的,传入NO-REFERRER这类写法同样可以生效。- 枚举命名本身也直观体现了策略语义:
NEVER_CLEAR(永不裁剪,对应unsafe-url)、CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE(降级时清空,对应no-referrer-when-downgrade)、ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN等。
另外,electron_api_url_loader.cc 中 fetch 式请求的默认策略为 blink::ReferrerUtils::GetDefaultNetReferrerPolicy(),并支持从 referrerPolicy 选项覆盖;而 system_network_context_manager.cc 中 enable_referrers = true 说明 Electron 的系统网络上下文是开启 referrer 支持的,策略裁剪才真正有意义。
实战场景一:loadURL 的 httpReferrer 参数
Referrer 对象最常见的入口是 loadURL 的 options.httpReferrer,其类型为 string | Referrer。文档中以下位置均如此声明:
- webContents.loadURL(
httpReferrer(string | Referrer) (optional) - An HTTP Referrer url.); - win.loadURL 与
<webview>.loadURL(webview-tag.md),参数列表与webContents.loadURL一致(httpReferrer、userAgent、extraHeaders、postData、baseURLForDataURL)。
在 electron_api_web_contents.cc 中可以看到两种入参的处理差异:
content::NavigationController::LoadURLParams params(url);
if (!options.Get("httpReferrer", ¶ms.referrer)) {
GURL http_referrer;
if (options.Get("httpReferrer", &http_referrer))
params.referrer =
content::Referrer(http_referrer.GetAsReferrer(),
network::mojom::ReferrerPolicy::kDefault);
}
- 传入 Referrer 对象:直接反序列化为
content::Referrer,你指定的policy会一路带到导航请求; - 传入字符串:先用
GURL解析,再包装为content::Referrer(url, ReferrerPolicy::kDefault),即策略固定为默认值。
因此,当你需要控制"来源页是 A 但只暴露 origin"这类行为时,必须传对象而不是字符串:
mainWindow.loadURL('https://example.com/target', {
httpReferrer: {
url: 'https://mysite.com/checkout',
policy: 'origin' // 跨源时只发送 https://mysite.com
}
})
仓库的 TypeScript 冒烟测试 main.ts 也验证了 loadURL 接受 httpReferrer 选项的类型签名:
mainWindow.loadURL('file://foo/bar', { userAgent: 'cool-agent', httpReferrer: 'greatReferrer' });
mainWindow.webContents.loadURL('file://foo/bar', { userAgent: 'cool-agent', httpReferrer: 'greatReferrer' });
实战场景二:did-create-window 事件中读取 referrer
当页面调用 window.open() 时,webContents 的 did-create-window 事件的 details 中带有 referrer 字段,其类型正是 Referrer 对象:
referrerReferrer - The referrer that will be passed to the new window. May or may not result in theRefererheader being sent, depending on the referrer policy.
文档特别强调:是否真的产生 Referer 头,取决于其中的 policy——这正是把 url 与 policy 放一起表达的原因。典型用法是在自定义 setWindowOpenHandler / 监听 did-create-window 时,根据来源页 URL 与策略做白名单校验:
mainWindow.webContents.on('did-create-window', (childWindow, details) => {
const { url, policy } = details.referrer
console.log(`opened from ${url} with policy ${policy}`)
// 例如:只有 policy 为 'no-referrer' 的来源才允许打开外链
})
实战场景三:context-menu 事件的 referrerPolicy 字段
webContents 与 <webview> 的 context-menu 事件参数中也带有 referrerPolicy 字段(类型同为 Referrer 结构,见 web-contents.md 与 webview-tag.md 的 context-menu 参数列表):
referrerPolicyReferrer - The referrer policy of the frame on which the menu is invoked.
它反映的是右键所在 frame 当前生效的 referrer 策略。当你自定义右键菜单、需要"在新窗口打开链接"等功能时,可以读取该字段判断当前页面的策略环境,再决定后续导航携带怎样的 referrer。
周边 API 中的 referrer 支持
Referrer 对象之外,Electron 还有几处相关能力,可对照理解策略的实际作用点:
-
net.request 的 referrerPolicy:
net模块发起的请求支持referrer与referrerPolicy选项。electron_api_url_loader.cc 中opts.Get("referrerPolicy", &request->referrer_policy)完成解析,且默认值为GetDefaultNetReferrerPolicy()。集成测试 api-net-spec.ts 验证了这一点:// The referrerPolicy must be unsafe-url because the referrer's origin // is http:// while the request url is https:// const urlRequest = net.request({ url: serverUrl, referrerPolicy: 'unsafe-url' });该测试用例正好演示了策略裁剪的实际影响:若 referrer 是
http://而目标为https://,默认策略下Referer会被清空,必须显式指定unsafe-url才能发出完整 URL。 -
webRequest 的 details.referrer:electron_api_web_request.cc 中
details->Set("referrer", request.referrer)将 referrer 注入onBeforeRequest等事件的 details(字符串形式)。因此你可以用session.defaultSession.webRequest在请求管线中观测或改写请求头,但注意details.referrer本身是只读的字符串字段,要影响最终发出的Referer,应通过onBeforeSendHeaders修改requestHeaders(见 web-request.md)。 -
net 重定向链路:electron_url_loader_factory.cc 在重定向时同步更新
request_.referrer与request_.referrer_policy,说明策略跟随重定向后的新 referrer 生效,与 Referrer-Policy 规范的语义一致。
小结
- Referrer 对象由
url(来源 URL)与policy(8 种取值之一的策略)组成,是 Electron 中表达"带策略的 Referer"的标准数据结构; - 策略字符串在 electron_api_url_loader.cc 的
Converter<net::ReferrerPolicy>中完成到 Chromium 枚举的映射,匹配大小写不敏感,且源码侧额外支持origin-when-cross-origin; - 需要自定义策略时,
loadURL必须传 Referrer 对象而非字符串,否则策略会被固定为kDefault; did-create-window的details.referrer、context-menu的referrerPolicy、net.request的referrerPolicy、webRequest的details.referrer构成了完整的观测与介入面,可结合 net.md 与 web-request.md 的文档进一步使用。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00