Saltar al contenido principal

protocol

Registrar un protocolo personalizado e interceptar las peticiones de protocolo existentes.

Proceso: principal

Un ejemplo de la implementación de un protocolo que tiene el mismo efecto que el protocolo 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())
})
})

Nota: Todos los métodos salvo los especificados pueden ser usados solo después de que el evento listo del módulo de la aplicación sea emitido.

Usando protocol con una partition o session personalizada

A protocol is registered to a specific Electron session object. Si no especificas una sesión, entonces tu protocol será aplicado a la sesión por defecto que Electron. Sin embargo, si defines un partition o session en tu webPreferences del browserWindow, luego esa ventana usará una sesión diferente y tu protocolo personalizado no funcionará si solo usas electron.protocol.XXX.

Para tener su protocolo personalizado trabajando con una sesión personalizada, necesitas registrarlo a esa sesión explícitamente.

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 } })
})

Métodos

El módulo protocolo tiene los siguientes métodos:

protocol.registerSchemesAsPrivileged(customSchemes)

Note: Este método solo puede ser usado antes de que el evento ready del modulo app sea emitido y solo puede ser llamado una vez.

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.

Un ejemplo de registro de un esquema privilegiado, que elude la Política de Seguridad Contenido:

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.

Registrar un esquema como estándar, permite a recursos relativos y absolutos ser resueltos correctamente cuando son servidos. De otra manera el esquema se comportaría como el protocolo archivo, pero sin la habilidad de resolver URLs relativas.

Por ejemplo cuando usted carga la siguiente carga con un protocolo personalizado sin registrar como un esquema estándar, esta imagen no será cargada debido a que un esquema que no es estandar puede no reconocer URLs relativas:

<body>
<img src='test.png'>
</body>

Registrar un esquema como estándar puede permitir el acceso a los archivos a travésAPI FileSystem. De otra manera el renderizador arrojará un error de seguridad en el sistema.

Por defecto las apis de web storage (localStorage, sessionStorage, webSQL, indexedDB, cookies) están deshabilitadas para esquemas no estándares. Así que en general, si quieres registrar un protocolo personalizado para reemplazar el protocolo http, tienes que registrarlo como un esquema estándar.

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 example https or my-app. This is the bit before the : in a URL.
  • handler Function<GlobalResponse | Promise<GlobalResponse>>

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.

Ejemplo:

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.

protocol.unhandle(scheme)

  • scheme string - scheme for which to remove the handler.

Removes a protocol handler registered with protocol.handle.

protocol.isProtocolHandled(scheme)

  • scheme string

Returns boolean - Whether scheme is already handled.

protocol.registerFileProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully registered

Registra un protocolo de scheme que enviará un archivo como repuesta. El handler será llamado con request y callback donde request es una solicitud entrante para el scheme.

Para controlar la solicitud, la retrollamada debe ser llamada con la ruta al archivo o un objeto que tiene una propiedad ruta, ejemplo callback(filePath) o callback({ path: filePath }). El filePath debe ser una ruta absoluta.

Por defecto el scheme es tratado como http:, que es analizado de forma diferente que los protocolos que siguen la "generic URI syntax" como file:.

protocol.registerBufferProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully registered

Registra un protocolo de esquema que enviará un Buffer como respuesta.

El uso es el mismo con registerFileProtocol, excepto que el callback debería ser llamado con un objeto Buffer o un objeto que tiene la propiedad data.

Ejemplo:

protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})

protocol.registerStringProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully registered

Registra un protocolo de esquema que enviará un string como respuesta.

El uso es el mismo con registerFileProtocol, excepto que el callback debería ser llamado con un objeto string o un objeto que tiene la propiedad data.

protocol.registerHttpProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully registered

Registra un protocolo de esquema que enviará una solicitud HTTP como respuesta.

El uso es el mismo con registerFileProtocol, excepto que el callback debería ser llamado con un objeto que tiene la propiedad url.

protocol.registerStreamProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully registered

Registra un protocolo de scheme que enviará un stream como respuesta.

El uso es el mismo con registerFileProtocol, excepto que el callback debería ser llamado con un objeto ReadableStream o un objeto que tiene la propiedad data.

Ejemplo:

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>')
})
})

Es posible pasar cualquier objeto que implementa la API readable stream (emite los eventos data/end/error). Por ejemplo, aquí está como puede devolver un archivo:

protocol.registerStreamProtocol('atom', (request, callback) => {
callback(fs.createReadStream('index.html'))
})

protocol.unregisterProtocol(scheme) Obsoleto

History
  • scheme string

Returns boolean - Whether the protocol was successfully unregistered

Anula el registro del protocolo predeterminado de esquema.

protocol.isProtocolRegistered(scheme) Obsoleto

History
  • scheme string

Devuelve boolean - Si el scheme ya está registrado.

protocol.interceptFileProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully intercepted

Intercepta el protocolo esquema y usa controlador como el controlador del nuevo protocolo lo cual enviará un archivo como respuesta.

protocol.interceptStringProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully intercepted

Intercepta el protocolo de scheme y usa el handler como el nuevo manejador del protocolo, el cual envía un string como respuesta.

protocol.interceptBufferProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully intercepted

Intercepta el protocolo de scheme y usa el handler como el nuevo manejador del protocolo, el cual envía un Buffer como respuesta.

protocol.interceptHttpProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully intercepted

Intercepta el protocolo scheme y utiliza el handler como el nuevo controlador del protocolo, el cual envía una nueva solicitud HTTP como respuesta.

protocol.interceptStreamProtocol(scheme, handler) Obsoleto

History

Returns boolean - Whether the protocol was successfully intercepted

Mismo que protocol.registerStreamProtocol, excepto que reemplaza un manejador de protocolo existente.

protocol.uninterceptProtocol(scheme) Obsoleto

History
  • scheme string

Returns boolean - Whether the protocol was successfully unintercepted

Elimina el interceptor instalado para el scheme y restaura su controlador original.

protocol.isProtocolIntercepted(scheme) Obsoleto

History
  • scheme string

Devuelve boolean - Si el scheme ya está interceptado.