protocol¶
注册自定义协议并拦截现有协议请求。
进程:主进程
实现一个与 file:// 协议具有相同效果的协议的示例:
const { app, protocol, net } = require('electron')
const path = require('node:path')
const url = require('node:url')
app.whenReady().then(() => {
protocol.handle('atom', (request) => {
const filePath = request.url.slice('atom://'.length)
return net.fetch(url.pathToFileURL(path.join(__dirname, filePath)).toString())
})
})
[!NOTE] 除特别说明外,所有方法只能在
app模块的ready事件 发出后使用。
使用 protocol 配合自定义 partition 或 session¶
协议会注册到特定的 Electron session 对象。如果你未指定 session,
则你的 protocol 将应用于 Electron 使用的默认 session。但是,如果你在
browserWindow 的 webPreferences 中定义了 partition 或 session,则该窗口将使用
不同的 session,如果你只是使用 electron.protocol.XXX,自定义协议将不会生效。
要让自定义协议与自定义 session 配合工作,你需要显式地将其注册到该 session。
const { app, BrowserWindow, net, protocol, session } = require('electron')
const path = require('node:path')
const url = require('node:url')
app.whenReady().then(() => {
const partition = 'persist:example'
const ses = session.fromPartition(partition)
ses.protocol.handle('atom', (request) => {
const filePath = request.url.slice('atom://'.length)
return net.fetch(url.pathToFileURL(path.resolve(__dirname, filePath)).toString())
})
const mainWindow = new BrowserWindow({ webPreferences: { partition } })
})
协议名称¶
RFC 3986 定义了有效的协议名称是什么:
协议名称由以字母开头,后跟字母、数字、加号(“+”)、句点(“.”)或连字符(“-”)任意组合的字符序列组成。 尽管协议名称不区分大小写,但规范形式为小写 […]。
方法¶
protocol 模块具有以下方法:
protocol.registerSchemesAsPrivileged(customSchemes)¶
customSchemesCustomScheme[]
[!NOTE] 此方法只能在
app模块的ready事件 发出之前使用,并且只能调用一次。
将 scheme 注册为标准协议、安全协议,绕过资源的 Content Security Policy,
允许注册 ServiceWorker,支持 fetch API、流式视频/音频以及 V8 代码缓存。
将某个权限的值指定为 true 即可启用该能力。
注册一个绕过 Content Security Policy 的特权协议的示例:
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
{ scheme: 'foo', privileges: { bypassCSP: true } }
])
标准协议遵循 RFC 3986 所称的通用 URI 语法。
例如,http 和 https 是标准协议,而 file 不是。
将协议注册为标准协议后,相对资源和绝对资源在提供时都能被正确解析。否则,
该协议的行为将类似于 file 协议,但无法解析相对 URL。
例如,如果你使用自定义协议加载以下页面,而没有将其注册为标准协议, 则图片不会加载,因为非标准协议无法识别相对 URL:
将协议注册为标准协议后,可以通过 FileSystem API 访问文件。 否则,渲染进程会针对该协议抛出安全错误。
默认情况下,Web 存储 API(localStorage、sessionStorage、webSQL、indexedDB、
cookies)对非标准协议是禁用的。因此,一般来说,如果你想注册一个自定义协议
来替代 http 协议,就必须将其注册为标准协议。
使用流(http 和 stream 协议)的协议应设置 stream: true。
<video> 和 <audio> HTML 元素默认期望协议会缓冲其响应。
stream 标志会配置这些元素以正确期望流式响应。
protocol.handle(scheme, handler)¶
schemestring - 要处理的协议,例如https或my-app。这是 URL 中:之前的部分。handlerFunction\<GlobalResponse | Promise\<GlobalResponse>>requestGlobalRequest
为 scheme 注册协议处理器。向使用该协议的 URL 发起的请求
将委托给此处理器,以确定应发送什么响应。
除了标准的 Request 字段外,当 Web 内容发起请求时,request.initiatorOrigin 会被设置为
发起请求的来源(例如 https://example.com,对于不透明来源则为 null);
对于浏览器自身发起的请求,该字段不存在。与 request.referrer 不同,
它不受请求页面控制,因此在决定是否响应请求时优先使用它。
可以返回 Response 或 Promise<Response>。
示例:
const { app, net, protocol } = require('electron')
const path = require('node:path')
const { pathToFileURL } = require('node:url')
protocol.registerSchemesAsPrivileged([
{
scheme: 'app',
privileges: {
standard: true,
secure: true,
supportFetchAPI: true
}
}
])
app.whenReady().then(() => {
protocol.handle('app', (req) => {
const { host, pathname } = new URL(req.url)
if (host === 'bundle') {
if (pathname === '/') {
return new Response('<h1>hello, world</h1>', {
headers: { 'content-type': 'text/html' }
})
}
// NB, this checks for paths that escape the bundle, e.g.
// app://bundle/../../secret_file.txt
const pathToServe = path.resolve(__dirname, pathname)
const relativePath = path.relative(__dirname, pathToServe)
const isSafe = relativePath && !relativePath.startsWith('..') && !path.isAbsolute(relativePath)
if (!isSafe) {
return new Response('bad', {
status: 400,
headers: { 'content-type': 'text/html' }
})
}
return net.fetch(pathToFileURL(pathToServe).toString())
} else if (host === 'api') {
return net.fetch('https://api.my-server.com/' + pathname, {
method: req.method,
headers: req.headers,
body: req.body
})
}
})
})
有关更多详细信息,请参阅 MDN 文档中的 Request 和 Response。
protocol.unhandle(scheme)¶
scheme字符串 - 要移除处理程序的 scheme。
移除通过 protocol.handle 注册的协议处理程序。
protocol.isProtocolHandled(scheme)¶
scheme字符串
返回 boolean - scheme 是否已被处理。
protocol.registerFileProtocol(scheme, handler) 已弃用¶
scheme字符串handler函数requestProtocolRequestcallback函数response(Buffer | ProtocolResponse)
返回 boolean - 协议是否成功注册
注册 scheme 协议,该协议将发送 Buffer 作为响应。
用法与 registerFileProtocol 相同,只是应使用 Buffer 对象或具有 data 属性的对象调用 callback。
示例:
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})
protocol.registerStringProtocol(scheme, handler) 已弃用¶
scheme字符串handler函数requestProtocolRequestcallback函数responseProtocolResponse
返回 boolean - 协议是否成功注册
注册 scheme 协议,该协议将发送 HTTP 请求作为响应。
用法与 registerFileProtocol 相同,只是应使用具有 url 属性的对象调用 callback。
protocol.registerStreamProtocol(scheme, handler) 已弃用¶
scheme字符串
返回 boolean - scheme 是否已注册。
protocol.interceptFileProtocol(scheme, handler) 已弃用¶
scheme字符串handler函数requestProtocolRequestcallback函数response(字符串 | ProtocolResponse)
返回 boolean - 协议是否成功拦截
拦截 scheme 协议,并使用 handler 作为该协议的新处理程序,
以 string 作为响应发送。
protocol.interceptBufferProtocol(scheme, handler) 已弃用¶
scheme字符串handler函数requestProtocolRequestcallback函数responseProtocolResponse
返回 boolean - 协议是否成功拦截
拦截 scheme 协议,并使用 handler 作为该协议的新处理程序,
以新的 HTTP 请求作为响应发送。
protocol.interceptStreamProtocol(scheme, handler) 已弃用¶
scheme字符串
返回 boolean - 协议是否已成功取消拦截
移除为 scheme 安装的拦截器,并恢复其原始处理程序。
protocol.isProtocolIntercepted(scheme) 已弃用¶
scheme字符串
返回 boolean - scheme 是否已被拦截。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 el/electron