メインコンテンツにスキップ

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 イベントが発行された後にのみ使用できます。

カスタム partition または sessionprotocol を使用する

プロトコルは、特定のElectron session オブジェクトに登録されます。セッションを指定しない場合、protocol はElectronが使用するデフォルトのセッションに適用されます。ただし、browserWindowwebPreferencespartition または session を定義した場合、そのウィンドウは別のセッションを使用し、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)

注: このメソッドは、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、cookies)は無効になっています。したがって、一般に、カスタムプロトコルを登録して http プロトコルを置き換える場合は、標準スキームとして登録する必要があります。

ストリームを使用するプロトコル(http およびストリームプロトコル)は、stream: true を設定する必要があります。<video> および <audio> HTML 要素は、デフォルトでプロトコルが応答をバッファリングすることを期待します。stream フラグは、それらの要素がストリーミング応答を正しく期待するように構成します。

protocol.handle(scheme, handler)

  • scheme string - 処理するスキーム。たとえば、https または my-app。これは、URL の : の前の部分です。
  • handler Function<GlobalResponse | Promise<GlobalResponse>>

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

詳細については、Request および Response の MDN ドキュメントを参照してください。

protocol.unhandle(scheme)

  • scheme string - ハンドラーを削除するスキーム。

protocol.handle で登録されたプロトコルハンドラーを削除します。

protocol.isProtocolHandled(scheme)

  • scheme string

boolean - scheme がすでに処理されているかどうかを返します。

protocol.registerFileProtocol(scheme, handler) 非推奨

履歴

boolean - プロトコルが正常に登録されたかどうかを返します

レスポンスとしてファイルを送信する scheme のプロトコルを登録します。handler は、requestcallback で呼び出され、requestscheme の受信リクエストです。

request を処理するには、callback は、ファイルのパスまたは path プロパティを持つオブジェクトで呼び出す必要があります。たとえば、callback(filePath) または callback({ path: filePath }) です。filePath は絶対パスである必要があります。

デフォルトでは、schemehttp: のように扱われ、「汎用 URI 構文」に従うプロトコル (file: など) とは異なる方法で解析されます。

protocol.registerBufferProtocol(scheme, handler) 非推奨

履歴

boolean - プロトコルが正常に登録されたかどうかを返します

レスポンスとして Buffer を送信する scheme のプロトコルを登録します。

使い方は registerFileProtocol と同じですが、callbackBuffer オブジェクトまたは data プロパティを持つオブジェクトで呼び出す必要がある点が異なります。

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

protocol.registerStringProtocol(scheme, handler) 非推奨

履歴

boolean - プロトコルが正常に登録されたかどうかを返します

レスポンスとして string を送信する scheme のプロトコルを登録します。

使い方は registerFileProtocol と同じですが、callbackstring または data プロパティを持つオブジェクトで呼び出す必要がある点が異なります。

protocol.registerHttpProtocol(scheme, handler) 非推奨

履歴

boolean - プロトコルが正常に登録されたかどうかを返します

HTTPリクエストをレスポンスとして送信するschemeのプロトコルを登録します。

callbackurlプロパティを持つオブジェクトで呼び出される必要がある点を除いて、使い方はregisterFileProtocolと同じです。

protocol.registerStreamProtocol(scheme, handler) 非推奨

履歴

boolean - プロトコルが正常に登録されたかどうかを返します

ストリームをレスポンスとして送信するschemeのプロトコルを登録します。

callbackReadableStreamオブジェクトまたはdataプロパティを持つオブジェクトで呼び出される必要がある点を除いて、使い方はregisterFileProtocolと同じです。

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

readable stream APIを実装する任意のオブジェクト(data/end/errorイベントを発行する)を渡すことができます。例えば、ファイルを返す方法は次のようになります。

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

protocol.unregisterProtocol(scheme) 非推奨

履歴
  • scheme string

戻り値 boolean - プロトコルの登録が正常に解除されたかどうか

schemeのカスタムプロトコルを登録解除します。

protocol.isProtocolRegistered(scheme) 非推奨

履歴
  • scheme string

戻り値 boolean - schemeがすでに登録されているかどうか。

protocol.interceptFileProtocol(scheme, handler) 非推奨

履歴

戻り値 boolean - プロトコルのインターセプトが成功したかどうか

schemeプロトコルをインターセプトし、レスポンスとしてファイルを送信するプロトコルの新しいハンドラとしてhandlerを使用します。

protocol.interceptStringProtocol(scheme, handler) 非推奨

履歴

戻り値 boolean - プロトコルのインターセプトが成功したかどうか

schemeプロトコルをインターセプトし、レスポンスとしてstringを送信するプロトコルの新しいハンドラとしてhandlerを使用します。

protocol.interceptBufferProtocol(scheme, handler) 非推奨

履歴

戻り値 boolean - プロトコルのインターセプトが成功したかどうか

schemeプロトコルをインターセプトし、レスポンスとしてBufferを送信するプロトコルの新しいハンドラとしてhandlerを使用します。

protocol.interceptHttpProtocol(scheme, handler) 非推奨

履歴

戻り値 boolean - プロトコルのインターセプトが成功したかどうか

schemeプロトコルをインターセプトし、新しいHTTPリクエストをレスポンスとして送信するプロトコルの新しいハンドラとしてhandlerを使用します。

protocol.interceptStreamProtocol(scheme, handler) 非推奨

履歴

戻り値 boolean - プロトコルのインターセプトが成功したかどうか

既存のプロトコルハンドラを置き換える点を除いて、protocol.registerStreamProtocolと同じです。

protocol.uninterceptProtocol(scheme) 非推奨

履歴
  • scheme string

戻り値 boolean - プロトコルのインターセプトが正常に解除されたかどうか

schemeにインストールされたインターセプターを削除し、元のハンドラを復元します。

protocol.isProtocolIntercepted(scheme) 非推奨

履歴
  • scheme string

戻り値 boolean - schemeがすでにインターセプトされているかどうか。