protocol (NetworkService) (Draft)

This document describes the new protocol APIs based on the NetworkService.

We don’t currently have an estimate of when we will enable the NetworkService by default in Electron, but as Chromium is already removing non-NetworkService code, we will probably switch before Electron 10.

The content of this document should be moved to protocol.md after we have enabled the NetworkService by default in Electron.

注册自定义协议并拦截基于现有协议的请求。

进程:主进程

实现与 file:// 协议具有相同效果的协议的示例:

  1. const { app, protocol } = require('electron')
  2. const path = require('path')
  3. app.on('ready', () => {
  4. protocol.registerFileProtocol('atom', (request, callback) => {
  5. const url = request.url.substr(7)
  6. callback({ path: path.normalize(`${__dirname}/${url}`) })
  7. })
  8. })

注意: 除了指定的方法, 其他方法只能在 app 模块的 ready 事件被触发后使用。

Using protocol with a custom partition or session

A protocol is registered to a specific Electron session object. If you don’t specify a session, then your protocol will be applied to the default session that Electron uses. However, if you define a partition or session on your browserWindow‘s webPreferences, then that window will use a different session and your custom protocol will not work if you just use electron.protocol.XXX.

To have your custom protocol work in combination with a custom session, you need to register it to that session explicitly.

  1. const { session, app, protocol } = require('electron')
  2. const path = require('path')
  3. app.on('ready', () => {
  4. const partition = 'persist:example'
  5. const ses = session.fromPartition(partition)
  6. ses.protocol.registerFileProtocol('atom', (request, callback) => {
  7. const url = request.url.substr(7)
  8. callback({ path: path.normalize(`${__dirname}/${url}`) })
  9. })
  10. mainWindow = new BrowserWindow({ webPreferences: { partition } })
  11. })

方法

protocol 模块具有以下方法:

protocol.registerSchemesAsPrivileged(customSchemes)

注意. 此方法只能在 appready 事件触发前调用,且只能调用一次

Registers the scheme as standard, secure, bypasses content security policy for resources, allows registering ServiceWorker and supports fetch API. Specify a privilege with the value of true to enable the capability.

An example of registering a privileged scheme, that bypasses Content Security Policy:

  1. const { protocol } = require('electron')
  2. protocol.registerSchemesAsPrivileged([
  3. { scheme: 'foo', privileges: { bypassCSP: true } }
  4. ])

标准scheme遵循 RFC 3986 所设定的 URI泛型语法 。 例如, httphttps 是标准协议, 而 file 不是。

Registering a scheme as standard allows relative and absolute resources to be resolved correctly when served. 否则, 该协议将表现为 file 协议, 而且,这种文件协议将不能解析相对路径。

例如, 当您使用自定义协议加载以下内容时,如果你不将其注册为标准scheme, 图片将不会被加载, 因为非标准scheme无法识别相对 路径:

  1. <body>
  2. <img src='test.png'>
  3. </body>

注册一个scheme作为标准scheme将允许其通过FileSystem 接口访问文件。 否则, 渲染器将会因为该scheme,而抛出一个安全性错误。

By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies) are disabled for non standard schemes. So in general if you want to register a custom protocol to replace the http protocol, you have to register it as a standard scheme.

protocol.registerFileProtocol(scheme, handler)

  • scheme String
  • handler Function

Registers a protocol of scheme that will send a file as the response. The handler will be called with request and callback where request is an incoming request for the scheme.

要处理 request, 应当使用文件的路径或具有 path 属性的对象来调用 callback。例如:callback(filePath)callback({ path: filePath }). The filePath must be an absolute path.

By default the scheme is treated like http:, which is parsed differently from protocols that follow the “generic URI syntax” like file:.

protocol.registerBufferProtocol(scheme, handler)

  • scheme String
  • handler Function

注册一个 scheme 协议, 将 Buffer作为响应发送

The usage is the same with registerFileProtocol, except that the callback should be called with either a Buffer object or an object that has the data property.

示例:

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

protocol.registerStringProtocol(scheme, handler)

  • scheme String
  • handler Function

注册一个 scheme 协议, 将 String 作为响应发送

The usage is the same with registerFileProtocol, except that the callback should be called with either a String or an object that has the data property.

protocol.registerHttpProtocol(scheme, handler)

  • scheme String
  • handler Function
    • request ProtocolRequest
    • callback Function
      • response ProtocolResponse

注册一个 scheme 协议, 将 HTTP 请求作为响应发送

The usage is the same with registerFileProtocol, except that the callback should be called with an object that has the url property.

protocol.registerStreamProtocol(scheme, handler)

  • scheme String
  • handler Function
    • request ProtocolRequest
    • callback Function

Registers a protocol of scheme that will send a stream as a response.

The usage is the same with registerFileProtocol, except that the callback should be called with either a ReadableStream object or an object that has the data property.

示例:

  1. const { protocol } = require('electron')
  2. const { PassThrough } = require('stream')
  3. function createStream (text) {
  4. const rv = new PassThrough() // PassThrough is also a Readable stream
  5. rv.push(text)
  6. rv.push(null)
  7. return rv
  8. }
  9. protocol.registerStreamProtocol('atom', (request, callback) => {
  10. callback({
  11. statusCode: 200,
  12. headers: {
  13. 'content-type': 'text/html'
  14. },
  15. data: createStream('<h5>Response</h5>')
  16. })
  17. })

It is possible to pass any object that implements the readable stream API (emits data/end/error events). For example, here’s how a file could be returned:

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

protocol.unregisterProtocol(scheme)

  • scheme String

取消对自定义scheme的注册

protocol.isProtocolRegistered(scheme)

  • scheme String

Returns Boolean - Whether scheme is already registered.

protocol.interceptFileProtocol(scheme, handler)

  • scheme String
  • handler Function

终止 scheme 协议, 并将 handler 作为该protocol新的处理方式,即返回一个file。

protocol.interceptStringProtocol(scheme, handler)

  • scheme String
  • handler Function

终止 scheme 协议, 并将 handler 作为该protocol新的处理方式,即返回一个String

protocol.interceptBufferProtocol(scheme, handler)

  • scheme String
  • handler Function

终止 scheme 协议, 并将 handler 作为该protocol新的处理方式,即返回一个Buffer

protocol.interceptHttpProtocol(scheme, handler)

  • scheme String
  • handler Function
    • request ProtocolRequest
    • callback Function
      • response ProtocolResponse

终止 scheme 协议, 并将 handler 作为该protocol新的处理方式,即返回一个新 HTTP 请求。

protocol.interceptStreamProtocol(scheme, handler)

  • scheme String
  • handler Function
    • request ProtocolRequest
    • callback Function

它与 registerStreamProtocol方法相同, 不过它是用来替换现有的protocol处理方式。

protocol.uninterceptProtocol(scheme)

  • scheme String

移除为 scheme 安装的拦截器,并还原其原始处理方式。

protocol.isProtocolIntercepted(scheme)

  • scheme String

Returns Boolean - Whether scheme is already intercepted.