프로토콜
커스텀 프로토콜을 등록하고 기존 프로토콜 요청을 가로챈다.
프로세스: 메인
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
또는 session
과 함께 protocol
사용하기
프로토콜은 특정 Electron session
객체에 등록된다. 세션을 지정하지 않으면, 프로토콜은 Electron이 사용하는 기본 세션에 적용된다. 그러나 browserWindow
의 webPreferences
에 partition
또는 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)
customSchemes
CustomScheme[]
참고: 이 메서드는 app
모듈의 ready
이벤트가 발생하기 전에만 사용할 수 있으며, 단 한 번만 호출할 수 있다.
scheme
을 표준으로 등록하고, 보안을 적용하며, 리소스에 대한 콘텐츠 보안 정책(CSP)을 우회하고, ServiceWorker 등록을 허용하며, fetch API, 스트리밍 비디오/오디오, 그리고 V8 코드 캐시를 지원한다. 특정 기능을 활성화하려면 true
값을 가진 권한을 지정한다.
콘텐츠 보안 정책(CSP)을 우회하는 권한이 있는 scheme을 등록하는 예시:
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
{ scheme: 'foo', privileges: { bypassCSP: true } }
])
표준 scheme은 RFC 3986에서 정의한 일반 URI 구문을 준수한다. 예를 들어 http
와 https
는 표준 scheme이지만, file
은 그렇지 않다.
scheme을 표준으로 등록하면 서비스될 때 상대 및 절대 리소스가 올바르게 해석된다. 그렇지 않으면 scheme은 file
프로토콜과 유사하게 동작하지만, 상대 URL을 해석할 수 없다.
예를 들어, 표준 scheme으로 등록하지 않은 커스텀 프로토콜로 다음 페이지를 로드하면, 이미지가 로드되지 않는다. 비표준 scheme은 상대 URL을 인식할 수 없기 때문이다:
<body>
<img src='test.png'>
</body>
scheme을 표준으로 등록하면 FileSystem API를 통해 파일에 접근할 수 있다. 그렇지 않으면 렌더러는 해당 scheme에 대해 보안 오류를 발생시킨다.
기본적으로 비표준 scheme에 대해 웹 스토리지 API(localStorage, sessionStorage, webSQL, indexedDB, 쿠키)가 비활성화된다. 따라서 일반적으로 http
프로토콜을 대체할 커스텀 프로토콜을 등록하려면 표준 scheme으로 등록해야 한다.
스트림을 사용하는 프로토콜(http 및 스트림 프로토콜)은 stream: true
를 설정해야 한다. <video>
와 <audio>
HTML 엘리먼트는 기본적으로 프로토콜이 응답을 버퍼링할 것을 기대한다. stream
플래그는 이러한 엘리먼트가 스트리밍 응답을 올바르게 처리하도록 설정한다.
protocol.handle(scheme, handler)
scheme
string - 처리할 스키마. 예를 들어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, 이 부분은 번들 외부로 이탈하는 경로를 확인한다. 예를 들어
// 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 - 핸들러를 제거할 scheme
protocol.handle
로 등록된 프로토콜 핸들러를 제거한다.
protocol.isProtocolHandled(scheme)
scheme
string
boolean
을 반환한다. 해당 scheme
이 이미 처리되었는지 여부를 나타낸다.
protocol.registerFileProtocol(scheme, handler)
Deprecated
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
(string | ProtocolResponse)
boolean
을 반환한다 - 프로토콜이 성공적으로 등록되었는지 여부를 나타낸다.
scheme
프로토콜을 등록하여 파일을 응답으로 보낸다. handler
는 request
와 callback
과 함께 호출되며, request
는 scheme
에 대한 들어오는 요청이다.
request
를 처리하기 위해 callback
은 파일 경로 또는 path
속성을 가진 객체와 함께 호출되어야 한다. 예를 들어 callback(filePath)
또는 callback({ path: filePath })
와 같이 사용한다. filePath
는 절대 경로여야 한다.
기본적으로 scheme
은 http:
처럼 처리되며, 이는 file:
과 같은 "일반 URI 구문"을 따르는 프로토콜과는 다르게 파싱된다.
protocol.registerBufferProtocol(scheme, handler)
Deprecated
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
(Buffer | ProtocolResponse)
boolean
을 반환 - 프로토콜이 성공적으로 등록되었는지 여부
Buffer
를 응답으로 전송하는 scheme
프로토콜을 등록한다.
registerFileProtocol
과 사용법이 동일하지만, callback
은 Buffer
객체 또는 data
속성을 가진 객체와 함께 호출해야 한다.
예제:
protocol.registerBufferProtocol('atom', (request, callback) => {
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})
protocol.registerStringProtocol(scheme, handler)
사용 중단됨
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
(string | ProtocolResponse)
boolean
을 반환 - 프로토콜이 성공적으로 등록되었는지 여부
scheme
프로토콜을 등록하고, string
을 응답으로 보낸다.
registerFileProtocol
과 사용법이 동일하지만, callback
은 string
또는 data
속성을 가진 객체와 함께 호출해야 한다.
protocol.registerHttpProtocol(scheme, handler)
더 이상 사용되지 않음
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
ProtocolResponse
boolean
을 반환 - 프로토콜이 성공적으로 등록되었는지 여부
scheme
의 프로토콜을 등록하여 HTTP 요청을 응답으로 보낸다.
사용법은 registerFileProtocol
과 동일하지만, callback
은 url
속성을 가진 객체로 호출해야 한다.
protocol.registerStreamProtocol(scheme, handler)
Deprecated
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
(ReadableStream | ProtocolResponse)
boolean
을 반환한다. 프로토콜이 성공적으로 등록되었는지 여부를 나타낸다.
scheme
프로토콜을 등록하여 스트림을 응답으로 보낸다.
사용법은 registerFileProtocol
과 동일하지만, callback
은 ReadableStream
객체 또는 data
속성을 가진 객체와 함께 호출해야 한다.
예제:
const { protocol } = require('electron')
const { PassThrough } = require('stream')
function createStream (text) {
const rv = new PassThrough() // PassThrough는 Readable 스트림이다
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>')
})
})
data
/end
/error
이벤트를 발생시키는 읽기 가능한 스트림 API를 구현한 모든 객체를 전달할 수 있다. 예를 들어, 파일을 반환하는 방법은 다음과 같다:
protocol.registerStreamProtocol('atom', (request, callback) => {
callback(fs.createReadStream('index.html'))
})
protocol.unregisterProtocol(scheme)
Deprecated
History
scheme
string
boolean
을 반환한다. 프로토콜이 성공적으로 등록 해제되었는지 여부를 나타낸다.
scheme
에 해당하는 커스텀 프로토콜을 등록 해제한다.
protocol.isProtocolRegistered(scheme)
사용 중단됨
History
scheme
string
boolean
을 반환합니다. scheme
이 이미 등록되었는지 여부를 나타냅니다.
protocol.interceptFileProtocol(scheme, handler)
Deprecated
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
(string | ProtocolResponse)
boolean
을 반환한다 - 프로토콜이 성공적으로 인터셉트되었는지 여부
scheme
프로토콜을 인터셉트하고, handler
를 프로토콜의 새로운 핸들러로 사용한다. 이 핸들러는 파일을 응답으로 보낸다.
protocol.interceptStringProtocol(scheme, handler)
더 이상 사용되지 않음
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
(string | ProtocolResponse)
boolean
을 반환 - 프로토콜이 성공적으로 가로채졌는지 여부
scheme
프로토콜을 가로채고 handler
를 프로토콜의 새로운 핸들러로 사용하며, 응답으로 string
을 보낸다.
protocol.interceptBufferProtocol(scheme, handler)
Deprecated
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
(Buffer | ProtocolResponse)
반환값 boolean
- 프로토콜이 성공적으로 인터셉트되었는지 여부
scheme
프로토콜을 인터셉트하고, handler
를 새로운 프로토콜 핸들러로 사용하여 Buffer
를 응답으로 보낸다.
protocol.interceptHttpProtocol(scheme, handler)
Deprecated
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
ProtocolResponse
boolean
을 반환 - 프로토콜이 성공적으로 인터셉트되었는지 여부를 나타낸다.
schema
프로토콜을 인터셉트하고, handler
를 프로토콜의 새로운 핸들러로 사용한다. 이 핸들러는 새로운 HTTP 요청을 응답으로 보낸다.
protocol.interceptStreamProtocol(scheme, handler)
Deprecated
History
scheme
stringhandler
Functionrequest
ProtocolRequestcallback
Functionresponse
(ReadableStream | ProtocolResponse)
boolean
을 반환 - 프로토콜이 성공적으로 가로채졌는지 여부
protocol.registerStreamProtocol
과 동일하지만, 기존 프로토콜 핸들러를 대체한다.
protocol.uninterceptProtocol(scheme)
Deprecated
History
scheme
string
boolean
을 반환 - 프로토콜의 인터셉트가 성공적으로 해제되었는지 여부
scheme
에 설치된 인터셉터를 제거하고 원래 핸들러를 복원한다.
protocol.isProtocolIntercepted(scheme)
더 이상 사용되지 않음
History
scheme
string
boolean
을 반환 - scheme
이 이미 인터셉트되었는지 여부를 나타냅니다.