詳解electron如何攔截網(wǎng)絡(luò)請(qǐng)求并處理響應(yīng)
需求背景
在electron中的web應(yīng)用離線方案,由于目前的web應(yīng)用已經(jīng)大量接入了,想要各個(gè)產(chǎn)線去對(duì)離線方案進(jìn)行大量配置更改,成本過高。所以期望離線方案能對(duì)現(xiàn)有web應(yīng)用進(jìn)行無侵入接入。
實(shí)現(xiàn)方案
electron版本:12.1.1
方案一 onBeforeRequest + 自定義協(xié)議
使用webRequest.onBeforeRequest攔截所有請(qǐng)求,通過判斷邏輯指定處理某些url。
這些特定的url,需要通過自定義協(xié)議處理。
注冊(cè)私有協(xié)議
const ses = session.fromPartition('persist:my-partition');
ses.protocol.registerFileProtocol('toLocal', (request, callback) => {
//這只是個(gè)舉例,實(shí)際需要通過request.url判斷使用哪個(gè)本地文件
callback({
path: '/Users/xxx/Documents/project/electron-react/dist/xxx.html',
statusCode: 200,
charset: 'utf-8',
mimeType: 'text/html',
});
對(duì)特定url進(jìn)行識(shí)別,轉(zhuǎn)發(fā)到私有協(xié)議中
ses.webRequest.onBeforeRequest({ urls: ['*://*/*'] }, (details: any, callback: any) => {
// 檢查請(qǐng)求URL是否為特定資源
if (details.url === 'https://xx.xx.com/') {
callback({
redirectURL: 'toLocal://xx.xx.com',
});
} else {
// 允許其他請(qǐng)求正常進(jìn)行
callback({});
}
});
自定義協(xié)議在攔截html時(shí),需要開啟訪問session(localstorage,cookie等)的權(quán)限
protocol.registerSchemesAsPrivileged([
{
scheme: 'toLocal',
privileges: {
standard: true,
secure: true,
supportFetchAPI: true,
bypassCSP: true,
corsEnabled: true,
},
},
]);
問題
使用onBeforeRequest+redirectURL轉(zhuǎn)發(fā)的url,會(huì)直接改變web中的request url。
私有協(xié)議無法使用cookie
在部分驗(yàn)證url的場(chǎng)景,會(huì)出現(xiàn)無權(quán)限/跨域問題
方案二 只使用攔截器
攔截自定義協(xié)議toLocal和https協(xié)議的請(qǐng)求,在https協(xié)議中處理指定url。命中后轉(zhuǎn)發(fā)到toLocal協(xié)議中,進(jìn)行本地文件的讀取。未命中則轉(zhuǎn)發(fā)請(qǐng)求。
ses.protocol.interceptFileProtocol('toLocal', (request, callback) => {
callback({
path: '/Users/xxx/Documents/project/electron-react/dist/xxx.html',
});
});
ses.protocol.interceptHttpProtocol('https', (request, callback) => {
if (request.url === 'https://xxx.xx.com/') {
callback({
url: 'toLocal://xxx.xx.com',
method: request.method,
});
} else {
const uploadData = request.uploadData && {
contentType: 'application/json',
data: request.uploadData.map((i) => i.bytes.toString()).join(''),
};
callback({
url: request.url,
method: request.method,
session: session.defaultSession,
uploadData,
});
}
});
問題
攔截器只能注冊(cè)一種,已先注冊(cè)的為主。后續(xù)注冊(cè)相同的scheme都會(huì)失敗。
由于以上問題,攔截請(qǐng)求時(shí),考慮使用interceptHttpProtocol。
不代理的請(qǐng)求需要轉(zhuǎn)發(fā)問題,request中的uploadData數(shù)據(jù)格式和response中的uploadData數(shù)據(jù)格式不一致。
當(dāng)前代碼中,處理post請(qǐng)求中,攜帶file時(shí)無法處理。目前正在解決中...
interceptHttpProtocol中的request和callback定義
// request定義
interface ProtocolRequest {
// Docs: https://electronjs.org/docs/api/structures/protocol-request
headers: Record<string, string>;
method: string;
referrer: string;
uploadData?: UploadData[];
url: string;
}
interface UploadData {
// Docs: https://electronjs.org/docs/api/structures/upload-data
/**
* UUID of blob data. Use ses.getBlobData method to retrieve the data.
*/
blobUUID?: string;
/**
* Content being sent.
*/
bytes: Buffer;
/**
* Path of file being uploaded.
*/
file?: string;
}
// callback傳參定義
interface ProtocolResponse {
// Docs: https://electronjs.org/docs/api/structures/protocol-response
/**
* The charset of response body, default is `"utf-8"`.
*/
charset?: string;
/**
* The response body. When returning stream as response, this is a Node.js readable
* stream representing the response body. When returning `Buffer` as response, this
* is a `Buffer`. When returning `String` as response, this is a `String`. This is
* ignored for other types of responses.
*/
data?: (Buffer) | (string) | (NodeJS.ReadableStream);
/**
* When assigned, the `request` will fail with the `error` number . For the
* available error numbers you can use, please see the net error list.
*/
error?: number;
/**
* An object containing the response headers. The keys must be String, and values
* must be either String or Array of String.
*/
headers?: Record<string, (string) | (string[])>;
/**
* The HTTP `method`. This is only used for file and URL responses.
*/
method?: string;
/**
* The MIME type of response body, default is `"text/html"`. Setting `mimeType`
* would implicitly set the `content-type` header in response, but if
* `content-type` is already set in `headers`, the `mimeType` would be ignored.
*/
mimeType?: string;
/**
* Path to the file which would be sent as response body. This is only used for
* file responses.
*/
path?: string;
/**
* The `referrer` URL. This is only used for file and URL responses.
*/
referrer?: string;
/**
* The session used for requesting URL, by default the HTTP request will reuse the
* current session. Setting `session` to `null` would use a random independent
* session. This is only used for URL responses.
*/
session?: Session;
/**
* The HTTP response code, default is 200.
*/
statusCode?: number;
/**
* The data used as upload data. This is only used for URL responses when `method`
* is `"POST"`.
*/
uploadData?: ProtocolResponseUploadData;
/**
* Download the `url` and pipe the result as response body. This is only used for
* URL responses.
*/
url?: string;
}
interface ProtocolResponseUploadData {
// Docs: https://electronjs.org/docs/api/structures/protocol-response-upload-data
/**
* MIME type of the content.
*/
contentType: string;
/**
* Content to be sent.
*/
data: (string) | (Buffer);
}
方案三:代理
安全過不去 棄
由于安全過不去,基本沒做調(diào)研,只知道有個(gè)setProxy
ses.setProxy()
總結(jié)
以上方案目前都不太滿足,調(diào)研了近3天,依舊沒有一個(gè)很好的解決方案。
在開始調(diào)研前的方案

我是真沒想到!我查了這么久,愣是沒找到能對(duì)webContent的網(wǎng)絡(luò)請(qǐng)求完全攔截的api?。。?/p>
方案一是目前最理想的方案了,開發(fā)成本極低。但是攔截html會(huì)出現(xiàn)問題,redirectURL導(dǎo)致web中的請(qǐng)求地址更改解決不了!
到此這篇關(guān)于詳解electron如何攔截網(wǎng)絡(luò)請(qǐng)求并處理響應(yīng)的文章就介紹到這了,更多相關(guān)electron攔截網(wǎng)絡(luò)請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
npm設(shè)置同時(shí)從多個(gè)包源加載包的方法
本文主要介紹了npm 設(shè)置同時(shí)從多個(gè)包源加載包的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
使用async、enterproxy控制并發(fā)數(shù)量的方法詳解
并發(fā)相信對(duì)大家來說都不陌生,這篇文章主要給大家介紹了關(guān)于使用async、enterproxy控制并發(fā)數(shù)量的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
使用nodeJs來安裝less及編譯less文件為css文件的方法
這篇文章主要介紹了使用nodeJs來安裝less及編譯less文件為css文件的方法,在文章末尾給大家補(bǔ)充介紹了通過nodejs將less文件轉(zhuǎn)為css文件的方法,具體內(nèi)容詳情大家通過本文學(xué)習(xí)吧2017-11-11
JavaScript第三方庫(kù)delegates的用法詳解
delegates?庫(kù)為?JavaScript?社區(qū)提供了一種高效的方式來聲明對(duì)象之間的委托關(guān)系,讓代碼結(jié)構(gòu)更加清晰,減少不必要的重復(fù),并提高可維護(hù)性,本文將詳細(xì)介紹如何在?Node.js?項(xiàng)目中使用?delegates?庫(kù)進(jìn)行高級(jí)委托,需要的朋友可以參考下2024-01-01
詳解HTTPS 的原理和 NodeJS 的實(shí)現(xiàn)
這篇文章主要介紹了詳解HTTPS 的原理和 NodeJS 的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
Node.js實(shí)現(xiàn)下載文件的兩種實(shí)用方式
最近優(yōu)化了幾個(gè)新人寫出的動(dòng)態(tài)表格文件下載接口的性能瓶頸,感覺非常有必要總結(jié)一篇文章作為文檔來拋磚引玉,這篇文章主要給大家介紹了關(guān)于Node.js實(shí)現(xiàn)下載文件的兩種實(shí)用方式,需要的朋友可以參考下2022-09-09
node中CDN 引入 與 npm 引入的區(qū)別小結(jié)
CDN引入和npm引入是前端集成第三方庫(kù)的兩種主要方式,各有特點(diǎn),下面就來詳細(xì)的介紹一下CDN 引入 與 npm 引入的區(qū)別,感興趣的可以了解一下2025-12-12

