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())
})
})
注意: 除非另有说明,否则所有方法只能在app
模块的ready
事件发出后才能使用。
在自定义partition
或session
中使用protocol
协议注册到特定的 Electron session
对象。如果您没有指定会话,则您的protocol
将应用于 Electron 使用的默认会话。但是,如果您在browserWindow
的webPreferences
上定义了partition
或session
,则该窗口将使用不同的会话,并且如果您只使用electron.protocol.XXX
,则您的自定义协议将不起作用。
要使您的自定义协议与自定义会话结合使用,您需要将其显式注册到该会话。
const { app, BrowserWindow, net, protocol, session } = require('electron')
const path = require('node:path')
const url = require('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 } })
})
方法
protocol
模块具有以下方法
protocol.registerSchemesAsPrivileged(customSchemes)
customSchemes
CustomScheme[]
注意: 此方法只能在app
模块的ready
事件发出之前使用,并且只能调用一次。
将scheme
注册为标准、安全、绕过资源的内容安全策略、允许注册 ServiceWorker、支持 fetch API、流式视频/音频和 V8 代码缓存。使用值为true
的特权来启用该功能。
注册绕过内容安全策略的特权方案的示例
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
{ scheme: 'foo', privileges: { bypassCSP: true } }
])
标准方案遵循 RFC 3986 中所谓的通用 URI 语法。例如,http
和https
是标准方案,而file
不是。
将方案注册为标准方案允许在提供服务时正确解析相对和绝对资源。否则,该方案的行为将类似于file
协议,但无法解析相对 URL。
例如,当您使用自定义协议加载以下页面但未将其注册为标准方案时,图像将不会加载,因为非标准方案无法识别相对 URL
<body>
<img src='test.png'>
</body>
将方案注册为标准方案将允许通过FileSystem API访问文件。否则,渲染器将为该方案抛出安全错误。
默认情况下,Web 存储 API(localStorage、sessionStorage、webSQL、indexedDB、cookie)对非标准方案禁用。因此,通常,如果您想注册一个自定义协议来替换http
协议,则必须将其注册为标准方案。
使用流的协议(http 和流协议)应设置stream: true
。<video>
和<audio>
HTML 元素默认情况下期望协议缓冲其响应。stream
标志配置这些元素以正确预期流式响应。
protocol.handle(scheme, handler)
scheme
字符串 - 要处理的方案,例如https
或my-app
。这是 URL 中冒号:
之前的部分。handler
Function<GlobalResponse | Promise<GlobalResponse>>request
GlobalRequest
为scheme
注册协议处理程序。对使用此方案的 URL 发出的请求将委托给此处理程序,以确定应发送什么响应。
可以返回Response
或Promise<Response>
。
示例
const { app, net, protocol } = require('electron')
const path = require('node:path')
const { pathToFileURL } = require('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
字符串 - 要为其删除处理程序的方案。
删除使用protocol.handle
注册的协议处理程序。
protocol.isProtocolHandled(scheme)
scheme
字符串
返回boolean
- scheme
是否已处理。
protocol.registerFileProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
(字符串 | ProtocolResponse)
返回boolean
- 协议是否已成功注册
注册一个scheme
协议,该协议将发送文件作为响应。handler
将使用request
和callback
调用,其中request
是对scheme
的传入请求。
要处理request
,应使用文件的路径或具有path
属性的对象调用callback
,例如callback(filePath)
或callback({ path: filePath })
。filePath
必须是绝对路径。
默认情况下,scheme
被视为http:
,其解析方式不同于遵循“通用 URI 语法”的协议,如file:
。
protocol.registerBufferProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
(Buffer | ProtocolResponse)
返回boolean
- 协议是否已成功注册
注册一个scheme
协议,该协议将发送Buffer
作为响应。
用法与registerFileProtocol
相同,除了callback
应使用Buffer
对象或具有data
属性的对象调用。
示例
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})
protocol.registerStringProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
(字符串 | ProtocolResponse)
返回boolean
- 协议是否已成功注册
注册一个scheme
协议,该协议将发送string
作为响应。
用法与registerFileProtocol
相同,除了callback
应使用string
或具有data
属性的对象调用。
protocol.registerHttpProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
ProtocolResponse
返回boolean
- 协议是否已成功注册
注册一个scheme
协议,该协议将发送 HTTP 请求作为响应。
用法与registerFileProtocol
相同,除了callback
应使用具有url
属性的对象调用。
protocol.registerStreamProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
(ReadableStream | ProtocolResponse)
返回boolean
- 协议是否已成功注册
注册一个scheme
协议,该协议将发送流作为响应。
其用法与registerFileProtocol
相同,区别在于callback
应该用一个ReadableStream
对象或具有data
属性的对象进行调用。
示例
const { protocol } = require('electron')
const { PassThrough } = require('stream')
function createStream (text) {
const rv = new PassThrough() // PassThrough is also a Readable stream
rv.push(text)
rv.push(null)
return rv
}
protocol.registerStreamProtocol('atom', (request, callback) => {
callback({
statusCode: 200,
headers: {
'content-type': 'text/html'
},
data: createStream('<h5>Response</h5>')
})
})
可以传递任何实现了可读流 API(发出data
/end
/error
事件)的对象。例如,以下是返回文件的示例
protocol.registerStreamProtocol('atom', (request, callback) => {
callback(fs.createReadStream('index.html'))
})
protocol.unregisterProtocol(scheme)
已弃用
scheme
字符串
返回boolean
- 是否已成功注销协议
注销scheme
的自定义协议。
protocol.isProtocolRegistered(scheme)
已弃用
scheme
字符串
返回boolean
- scheme
是否已注册。
protocol.interceptFileProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
(字符串 | ProtocolResponse)
返回boolean
- 是否已成功拦截协议
拦截scheme
协议,并使用handler
作为协议的新处理器,该处理器发送文件作为响应。
protocol.interceptStringProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
(字符串 | ProtocolResponse)
返回boolean
- 是否已成功拦截协议
拦截scheme
协议,并使用handler
作为协议的新处理器,该处理器发送一个string
作为响应。
protocol.interceptBufferProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
(Buffer | ProtocolResponse)
返回boolean
- 是否已成功拦截协议
拦截scheme
协议,并使用handler
作为协议的新处理器,该处理器发送一个Buffer
作为响应。
protocol.interceptHttpProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
ProtocolResponse
返回boolean
- 是否已成功拦截协议
拦截scheme
协议,并使用handler
作为协议的新处理器,该处理器发送一个新的HTTP请求作为响应。
protocol.interceptStreamProtocol(scheme, handler)
已弃用
scheme
字符串handler
函数request
ProtocolRequestcallback
函数response
(ReadableStream | ProtocolResponse)
返回boolean
- 是否已成功拦截协议
与protocol.registerStreamProtocol
相同,只是它替换了现有的协议处理器。
protocol.uninterceptProtocol(scheme)
已弃用
scheme
字符串
返回boolean
- 是否已成功取消拦截协议
删除为scheme
安装的拦截器,并恢复其原始处理器。
protocol.isProtocolIntercepted(scheme)
已弃用
scheme
字符串
返回boolean
- scheme
是否已被拦截。