詳解electron如何攔截網絡請求并處理響應
需求背景
在electron
中的web應用離線方案,由于目前的web應用已經大量接入了,想要各個產線去對離線方案進行大量配置更改,成本過高。所以期望離線方案能對現有web應用進行無侵入接入。
實現方案
electron版本:12.1.1
方案一 onBeforeRequest + 自定義協(xié)議
使用webRequest.onBeforeRequest
攔截所有請求,通過判斷邏輯指定處理某些url。
這些特定的url,需要通過自定義協(xié)議處理。
注冊私有協(xié)議
const ses = session.fromPartition('persist:my-partition'); ses.protocol.registerFileProtocol('toLocal', (request, callback) => { //這只是個舉例,實際需要通過request.url判斷使用哪個本地文件 callback({ path: '/Users/xxx/Documents/project/electron-react/dist/xxx.html', statusCode: 200, charset: 'utf-8', mimeType: 'text/html', });
對特定url進行識別,轉發(fā)到私有協(xié)議中
ses.webRequest.onBeforeRequest({ urls: ['*://*/*'] }, (details: any, callback: any) => { // 檢查請求URL是否為特定資源 if (details.url === 'https://xx.xx.com/') { callback({ redirectURL: 'toLocal://xx.xx.com', }); } else { // 允許其他請求正常進行 callback({}); } });
自定義協(xié)議在攔截html時,需要開啟訪問session(localstorage,cookie等)的權限
protocol.registerSchemesAsPrivileged([ { scheme: 'toLocal', privileges: { standard: true, secure: true, supportFetchAPI: true, bypassCSP: true, corsEnabled: true, }, }, ]);
問題
使用onBeforeRequest
+redirectURL
轉發(fā)的url,會直接改變web中的request url
。
私有協(xié)議無法使用cookie
在部分驗證url的場景,會出現無權限/跨域問題
方案二 只使用攔截器
攔截自定義協(xié)議toLocal
和https
協(xié)議的請求,在https協(xié)議中處理指定url。命中后轉發(fā)到toLocal
協(xié)議中,進行本地文件的讀取。未命中則轉發(fā)請求。
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, }); } });
問題
攔截器只能注冊一種,已先注冊的為主。后續(xù)注冊相同的scheme都會失敗。
由于以上問題,攔截請求時,考慮使用interceptHttpProtocol
。
不代理的請求需要轉發(fā)問題,request
中的uploadData
數據格式和response
中的uploadData
數據格式不一致。
當前代碼中,處理post請求中,攜帶file時無法處理。目前正在解決中...
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); }
方案三:代理
安全過不去 棄
由于安全過不去,基本沒做調研,只知道有個setProxy
ses.setProxy()
總結
以上方案目前都不太滿足,調研了近3天,依舊沒有一個很好的解決方案。
在開始調研前的方案
我是真沒想到!我查了這么久,愣是沒找到能對webContent的網絡請求完全攔截的api!?。?/p>
方案一是目前最理想的方案了,開發(fā)成本極低。但是攔截html會出現問題,redirectURL導致web中的請求地址更改解決不了!
到此這篇關于詳解electron如何攔截網絡請求并處理響應的文章就介紹到這了,更多相關electron攔截網絡請求內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
基于node.js依賴express解析post請求四種數據格式
本篇文章主要介紹了node.js依賴express解析post請求四種數據格式,主要是www-form-urlencoded,form-data,application/json,text/xml,有興趣的可以了解一下。2017-02-02Nodejs連接mysql并實現增、刪、改、查操作的方法詳解
這篇文章主要介紹了Nodejs連接mysql并實現增、刪、改、查操作的方法,結合實例形式詳細分析了nodejs針對mysql數據庫的的連接、mysql數據庫的創(chuàng)建及nodejs針對mysql增刪改查等相關操作具體實現技巧,需要的朋友可以參考下2018-01-01