diff --git a/src/IpcMainHandler.ts b/src/IpcMainHandler.ts new file mode 100644 index 0000000..28bcea8 --- /dev/null +++ b/src/IpcMainHandler.ts @@ -0,0 +1,101 @@ +import { ipcMain, screen, session } from "electron"; +import http from 'http'; +import https from 'https'; +import { URL } from 'url'; + +export function initialize(): void { + // Get primary display(需要注意:size 是逻辑像素尺寸(logical screen size),已被 DPI 缩放影响,需要除以 DPI 缩放比例才是物理像素尺寸(physical screen size)) + ipcMain.handle('get-primary-display', () => screen.getPrimaryDisplay()); + + // Check if the URL is available + ipcMain.handle('check-url-available', async (event, rawUrl: string) => { + try { + const url: URL = new URL(rawUrl); + const lib = url.protocol === 'https:' ? https : http; + + return await new Promise((resolve) => { + // 先用HEAD请求,如果遇到403,则再用GET请求再试一次(部分服务器可能禁止HEAD请求)。 + const requestOptions: http.RequestOptions | https.RequestOptions = { + hostname: url.hostname, + port: url.port || undefined, + path: url.pathname + url.search, + headers: { + 'Accept': '*/*', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' + } + }; + const headReq = lib.request( + { + method: 'HEAD', + timeout: 3000, + ...requestOptions + }, + (res) => { + console.log('check-url-available HEAD', url.toString(), res.statusCode, res.statusMessage); + if (res.statusCode === 403) { + headReq.destroy() + const getReq = lib.get({ + method: 'GET', + ...requestOptions + }, (res) => { + console.log('check-url-available GET', url.toString(), res.statusCode, res.statusMessage); + resolve({ ok: true, status: res.statusCode, message: res.statusMessage }); + getReq.destroy() + }); + getReq.on('error', (err) => { + resolve({ ok: false, status: -1, message: err.message }); + }); + getReq.on('timeout', () => { + resolve({ ok: false, status: -1, message: 'GET Timeout' }); + getReq.destroy(); + }); + } else { + resolve({ ok: true, status: res.statusCode, message: res.statusMessage }); + headReq.destroy(); + } + } + ); + + headReq.on('error', (err) => { + resolve({ ok: false, status: -1, message: err.message }); + }); + + headReq.on('timeout', () => { + resolve({ ok: false, status: -1, message: 'HEAD Timeout' }); + headReq.destroy(); + }); + + headReq.end(); + }) + } catch (e) { + return { ok: false, status: -1, message: 'Invalid URL' }; + } + }); + + // Set webview‘s cookie + ipcMain.handle('set-webview-cookie', async (event, url: string, cookie: string) => { + try { + const parsedUrl = new URL(url); + const cookies: Array<{ Key: string, Value: string }> = JSON.parse(cookie); + + for (const cookieItem of cookies) { + await session.defaultSession.cookies.set({ + url: url, + name: cookieItem.Key.trim(), + value: cookieItem.Value.trim(), + domain: parsedUrl.hostname, + path: '/', + secure: parsedUrl.protocol === 'https:', + httpOnly: true + }); + } + return true; + } catch (error) { + console.error('设置cookie失败:', error); + return false; + } + }); +} + diff --git a/src/main.ts b/src/main.ts index 107348f..30caada 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,8 +1,7 @@ -import { app, BrowserWindow, globalShortcut, ipcMain, Menu, session, screen, Tray } from 'electron'; +import { app, BrowserWindow, globalShortcut, Menu, Tray } from 'electron'; import path from 'node:path'; import started from 'electron-squirrel-startup'; -import http from 'http'; -import https from 'https'; +import { initialize } from './IpcMainHandler'; const isDevelopment: boolean = process.env.NODE_ENV === 'development'; @@ -27,100 +26,6 @@ if (started) { app.exit(0); // 使用 exit 而不是 quit,确保立即退出 } -// Get primary display(需要注意:size 是逻辑像素尺寸(logical screen size),已被 DPI 缩放影响,需要除以 DPI 缩放比例才是物理像素尺寸(physical screen size)) -ipcMain.handle('get-primary-display', () => screen.getPrimaryDisplay()); - -// Check if the URL is available -ipcMain.handle('check-url-available', async (event, rawUrl: string) => { - try { - const url: URL = new URL(rawUrl); - const lib = url.protocol === 'https:' ? https : http; - - return await new Promise((resolve) => { - // 先用HEAD请求,如果遇到403,则再用GET请求再试一次(部分服务器可能禁止HEAD请求)。 - const requestOptions: http.RequestOptions | https.RequestOptions = { - hostname: url.hostname, - port: url.port || undefined, - path: url.pathname + url.search, - headers: { - 'Accept': '*/*', - 'Accept-Encoding': 'gzip, deflate, br', - 'Connection': 'keep-alive', - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' - } - }; - const headReq = lib.request( - { - method: 'HEAD', - timeout: 3000, - ...requestOptions - }, - (res) => { - console.log('check-url-available HEAD', url.toString(), res.statusCode, res.statusMessage); - if (res.statusCode === 403) { - headReq.destroy() - const getReq = lib.get({ - method: 'GET', - ...requestOptions - }, (res) => { - console.log('check-url-available GET', url.toString(), res.statusCode, res.statusMessage); - resolve({ ok: true, status: res.statusCode, message: res.statusMessage }); - getReq.destroy() - }); - getReq.on('error', (err) => { - resolve({ ok: false, status: -1, message: err.message }); - }); - getReq.on('timeout', () => { - resolve({ ok: false, status: -1, message: 'GET Timeout' }); - getReq.destroy(); - }); - } else { - resolve({ ok: true, status: res.statusCode, message: res.statusMessage }); - headReq.destroy(); - } - } - ); - - headReq.on('error', (err) => { - resolve({ ok: false, status: -1, message: err.message }); - }); - - headReq.on('timeout', () => { - resolve({ ok: false, status: -1, message: 'HEAD Timeout' }); - headReq.destroy(); - }); - - headReq.end(); - }) - } catch (e) { - return { ok: false, status: -1, message: 'Invalid URL' }; - } -}); - -// Set webview‘s cookie -ipcMain.handle('set-webview-cookie', async (event, url: string, cookie: string) => { - try { - const parsedUrl = new URL(url); - const cookies: Array<{ Key: string, Value: string }> = JSON.parse(cookie); - - for (const cookieItem of cookies) { - await session.defaultSession.cookies.set({ - url: url, - name: cookieItem.Key.trim(), - value: cookieItem.Value.trim(), - domain: parsedUrl.hostname, - path: '/', - secure: parsedUrl.protocol === 'https:', - httpOnly: true - }); - } - return true; - } catch (error) { - console.error('设置cookie失败:', error); - return false; - } -}); - const createWindow = () => { // Create the browser window. const win = new BrowserWindow({ @@ -257,3 +162,5 @@ app.whenReady().then(() => { } }); }); + +initialize();