跳到主要內容

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 事件發射後使用。

搭配自訂 partitionsession 使用 protocol

協定會註冊到特定的 Electron session 物件。如果您未指定 session,則您的 protocol 將會套用至 Electron 使用的預設 session。但是,如果您在 browserWindowwebPreferences 上定義了 partitionsession,則該視窗將使用不同的 session,而且如果您僅使用 electron.protocol.XXX,您的自訂協定將無法運作。

若要讓您的自訂協定與自訂 session 搭配運作,您需要明確地將其註冊到該 session。

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)

注意: 此方法只能在 app 模組的 ready 事件發射之前使用,而且只能呼叫一次。

scheme 註冊為標準、安全、繞過資源的內容安全策略、允許註冊 ServiceWorker、支援 fetch API、串流視訊/音訊和 V8 程式碼快取。使用值為 true 的權限來啟用此功能。

註冊具備權限的協定(會繞過內容安全策略)的範例

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

標準協定遵守 RFC 3986 所稱的 通用 URI 語法。例如,httphttps 是標準協定,而 file 不是。

將協定註冊為標準協定,可在提供服務時正確解析相對和絕對資源。否則,協定的行為會像 file 協定,但無法解析相對 URL。

例如,當您使用自訂協定載入以下頁面,而未將其註冊為標準協定時,影像將不會載入,因為非標準協定無法辨識相對 URL

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

將協定註冊為標準協定,將允許透過 FileSystem API 存取檔案。否則,渲染器會針對此協定擲回安全性錯誤。

預設情況下,網頁儲存 API(localStorage、sessionStorage、webSQL、indexedDB、cookies)對於非標準協定會停用。因此,一般而言,如果您想要註冊自訂協定來取代 http 協定,您必須將其註冊為標準協定。

使用串流的協定(http 和 stream 協定)應設定 stream: true<video><audio> HTML 元素預期協定預設會緩衝其回應。stream 旗標會設定這些元素以正確預期串流回應。

protocol.handle(scheme, handler)

  • scheme 字串 - 要處理的協定,例如 httpsmy-app。這是 URL 中 : 之前的位元。
  • handler Function<GlobalResponse | Promise<GlobalResponse>>

scheme 註冊協定處理常式。對具有此協定的 URL 發出的請求將委派給此處理常式,以判斷應傳送的回應。

可以傳回 ResponsePromise<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 文件中的 RequestResponse

protocol.unhandle(scheme)

  • scheme 字串 - 要移除處理常式的協定。

移除使用 protocol.handle 註冊的協定處理常式。

protocol.isProtocolHandled(scheme)

  • scheme 字串

傳回 boolean - scheme 是否已處理。

protocol.registerFileProtocol(scheme, handler) 已停用

歷史記錄

傳回 boolean - 協定是否已成功註冊

註冊 scheme 的協定,該協定會將檔案作為回應傳送。將會使用 requestcallback 呼叫 handler,其中 request 是針對 scheme 的傳入請求。

若要處理 request,應使用檔案路徑或具有 path 屬性的物件呼叫 callback,例如 callback(filePath)callback({ path: filePath })filePath 必須是絕對路徑。

預設情況下,scheme 會被視為 http:,這與遵循「通用 URI 語法」(如 file:)的協定不同。

protocol.registerBufferProtocol(scheme, handler) 已停用

歷史記錄

傳回 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) 已停用

歷史記錄

傳回 boolean - 協定是否已成功註冊

註冊 scheme 的協定,該協定會將 string 作為回應傳送。

用法與 registerFileProtocol 相同,不同之處在於應使用 string 或具有 data 屬性的物件呼叫 callback

protocol.registerHttpProtocol(scheme, handler) 已停用

歷史記錄

傳回 boolean - 協定是否已成功註冊

註冊 scheme 的協定,該協定會將 HTTP 請求作為回應傳送。

用法與 registerFileProtocol 相同,不同之處在於應使用具有 url 屬性的物件呼叫 callback

protocol.registerStreamProtocol(scheme, handler) 已停用

歷史記錄

傳回 boolean - 協定是否已成功註冊

註冊 scheme 的協定,該協定會將串流作為回應傳送。

用法與 registerFileProtocol 相同,不同之處在於應使用 ReadableStream 物件或具有 data 屬性的物件呼叫 callback

範例

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) 已停用

歷史記錄

傳回 boolean - 協定是否已成功攔截

攔截 scheme 協定,並使用 handler 作為協定的新處理常式,該處理常式會將檔案作為回應傳送。

protocol.interceptStringProtocol(scheme, handler) 已停用

歷史記錄

傳回 boolean - 協定是否已成功攔截

攔截 scheme 協定,並使用 handler 作為協定的新處理常式,該處理常式會將 string 作為回應傳送。

protocol.interceptBufferProtocol(scheme, handler) 已停用

歷史記錄

傳回 boolean - 協定是否已成功攔截

攔截 scheme 協定,並使用 handler 作為協定的新處理常式,該處理常式會將 Buffer 作為回應傳送。

protocol.interceptHttpProtocol(scheme, handler) 已停用

歷史記錄

傳回 boolean - 協定是否已成功攔截

攔截 scheme 協定,並使用 handler 作為協定的新處理常式,該處理常式會將新的 HTTP 請求作為回應傳送。

protocol.interceptStreamProtocol(scheme, handler) 已停用

歷史記錄

傳回 boolean - 協定是否已成功攔截

protocol.registerStreamProtocol 相同,不同之處在於它會取代現有的協定處理常式。

protocol.uninterceptProtocol(scheme) 已停用

歷史記錄
  • scheme 字串

傳回 boolean - 協定是否已成功取消攔截

移除為 scheme 安裝的攔截器,並還原其原始處理常式。

protocol.isProtocolIntercepted(scheme) 已停用

歷史記錄
  • scheme 字串

傳回 boolean - scheme 是否已被攔截。