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
事件後使用。
將 protocol
與自訂 partition
或 session
搭配使用
協定會註冊到特定的 Electron session
物件。如果您沒有指定 session,則您的 protocol
將會套用到 Electron 使用的預設 session。但是,如果您在 browserWindow
的 webPreferences
上定義 partition
或 session
,則該視窗將會使用不同的 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)
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
(string | ProtocolResponse)
傳回 boolean
- 協定是否已成功註冊
註冊 scheme
的協定,該協定會將檔案做為回應傳送。將會使用 request
和 callback
呼叫 handler
,其中 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
相同,只是應該使用 Buffer
物件或具有 data
屬性的物件呼叫 callback
。
範例
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})
protocol.registerStringProtocol(scheme, handler)
已棄用
scheme
字串handler
函數request
ProtocolRequestcallback
函數response
(string | ProtocolResponse)
傳回 boolean
- 協定是否已成功註冊
註冊 scheme
的協定,該協定會傳送 string
做為回應。
用法與 registerFileProtocol
相同,只是應該使用 string
或具有 data
屬性的物件呼叫 callback
。
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
(string | ProtocolResponse)
回傳 boolean
- 是否成功攔截協定
攔截 scheme
協定,並使用 handler
作為協定的新處理程式,以檔案作為回應。
protocol.interceptStringProtocol(scheme, handler)
已棄用
scheme
字串handler
函數request
ProtocolRequestcallback
函數response
(string | 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
是否已攔截。