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())
})
})
Примечание: Все методы, если не указано другого, могут быть использованы только после того, как событие ready
модуля app
будет отправлено.
Использование протокола protocol
с пользовательским разделом partition
или сеансом session
Протокол регистрируется для определенного Electron объекта session
. Если вы не укажете сеанс, то ваш protocol
будет применен сеансу по умолчанию, который использует Electron. Однако, если вы определите partition
или session
в браузереWindow
в webPreferences
, то это окно будет использовать другой сеанс, и ваш пользовательский протокол не будет работать, если вы просто используете 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[]
Примечание: Этот метод можно использовать только до отправки события ready
модуля app
и может быть вызван только один раз.
Registers the scheme
as standard, secure, bypasses content security policy for resources, allows registering ServiceWorker, supports fetch API, streaming video/audio, and V8 code cache. Specify a privilege with the value of true
to enable the capability.
Пример регистрации привилегированной схемы, которая обходит Политику безопасности контента:
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
{ scheme: 'foo', privileges: { bypassCSP: true } }
])
A standard scheme adheres to what RFC 3986 calls generic URI syntax. For example http
and https
are standard schemes, while file
is not.
Регистрация схемы в качестве стандартной позволяет правильно разрешать относительные и абсолютные ресурсы при обслуживании. В противном случае схема будет вести себя как протокол file
, но без возможности разрешения относительных URL-адресов.
Например, когда вы загружаете следующую страницу с помощью пользовательского протокола, не регистрируя его как стандартную схему, изображение не будет загружено, потому что нестандартные схемы не могут распознать относительные URL-адреса:
<body>
<img src='test.png'>
</body>
Registering a scheme as standard will allow access to files through the FileSystem API. В противном случае программа для схемы выдаст ошибку безопасности.
По умолчанию веб-хранилище Apis (localStorage, sessionStorage, webSQL, indexedDB, cookies) отключено для нестандартных схем. Поэтому в общем случае, если вы хотите зарегистрировать пользовательский протокол для замены протокола http
, необходимо зарегистрировать его как стандартную схему.
Protocols that use streams (http and stream protocols) should set stream: true
. The <video>
and <audio>
HTML elements expect protocols to buffer their responses by default. The stream
flag configures those elements to correctly expect streaming responses.
protocol.handle(scheme, handler)
scheme
string - scheme to handle, for examplehttps
ormy-app
. This is the bit before the:
in a URL.handler
Function<GlobalResponse | Promise<GlobalResponse>>request
GlobalRequest
Register a protocol handler for scheme
. Requests made to URLs with this scheme will delegate to this handler to determine what response should be sent.
Either a Response
or a Promise<Response>
can be returned.
Пример:
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
})
}
})
})
See the MDN docs for Request
and Response
for more details.