优化检测URL是否有效方法,使其更贴近浏览器访问效果,以及当HEAD请求后收到403响应时,再用GET请求一次(也许Web服务器禁止了HEAD请求)。
This commit is contained in:
parent
51087027c8
commit
85036de5c3
@ -216,7 +216,7 @@ export interface TagResolutionConfig {
|
||||
/**
|
||||
* 缩放比例
|
||||
*/
|
||||
Percentage: number;
|
||||
Percentage: string | number;
|
||||
/**
|
||||
* 特殊页面
|
||||
*/
|
||||
@ -234,7 +234,7 @@ export interface SpecialPUrlItem {
|
||||
/**
|
||||
* 特殊页面缩放比例
|
||||
*/
|
||||
SPPer: number;
|
||||
SPPer: string | number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
67
src/main.ts
67
src/main.ts
@ -5,6 +5,8 @@ import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
import { URL } from 'url';
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV === 'development';
|
||||
|
||||
// Ensure only one instance is running
|
||||
const gotTheLock = app.requestSingleInstanceLock();
|
||||
if (!gotTheLock) {
|
||||
@ -32,34 +34,64 @@ 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 = new URL(rawUrl);
|
||||
const url: URL = new URL(rawUrl);
|
||||
const lib = url.protocol === 'https:' ? https : http;
|
||||
|
||||
return await new Promise((resolve) => {
|
||||
const req = lib.request(
|
||||
// 先用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',
|
||||
hostname: url.hostname,
|
||||
port: url.port || undefined,
|
||||
path: url.pathname + url.search,
|
||||
timeout: 3000,
|
||||
...requestOptions
|
||||
},
|
||||
(res) => {
|
||||
resolve({ ok: true, status: res.statusCode })
|
||||
req.destroy()
|
||||
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, error: err.message });
|
||||
});
|
||||
getReq.on('timeout', () => {
|
||||
resolve({ ok: false, error: 'Timeout' });
|
||||
getReq.destroy();
|
||||
});
|
||||
} else {
|
||||
resolve({ ok: true, status: res.statusCode, message: res.statusMessage });
|
||||
headReq.destroy();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
req.on('error', (err) => {
|
||||
resolve({ ok: false, error: err.message })
|
||||
headReq.on('error', (err) => {
|
||||
resolve({ ok: false, error: err.message });
|
||||
});
|
||||
|
||||
req.on('timeout', () => {
|
||||
req.destroy()
|
||||
resolve({ ok: false, error: 'Timeout' })
|
||||
headReq.on('timeout', () => {
|
||||
resolve({ ok: false, error: 'Timeout' });
|
||||
headReq.destroy();
|
||||
});
|
||||
|
||||
req.end();
|
||||
headReq.end();
|
||||
})
|
||||
} catch (e) {
|
||||
return { ok: false, error: 'Invalid URL' };
|
||||
@ -141,7 +173,9 @@ const createWindow = () => {
|
||||
|
||||
win.webContents.on('did-attach-webview', (event, webContents) => {
|
||||
webContents.setWindowOpenHandler((details) => {
|
||||
console.log('webview-new-window', webContents, details);
|
||||
if (isDevelopment) {
|
||||
console.log('webview-new-window', webContents, details);
|
||||
}
|
||||
win.webContents.send('webview-new-window', webContents.id, details.url);
|
||||
return { action: 'deny' };
|
||||
});
|
||||
@ -172,6 +206,9 @@ const createWindow = () => {
|
||||
}
|
||||
};
|
||||
globalShortcut.register("CommandOrControl+Shift+I", handleDevTools);
|
||||
if (isDevelopment) {
|
||||
win.webContents.openDevTools();
|
||||
}
|
||||
|
||||
// and load the login.html of the app.
|
||||
if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
|
||||
@ -185,7 +222,7 @@ const createWindow = () => {
|
||||
{ label: '显示窗口', click: () => win.show() },
|
||||
{ label: '退出程序', click: () => app.exit() }
|
||||
]);
|
||||
const iconPath = process.env.NODE_ENV === 'development' ? path.join(__dirname, '../../assets/tray.png') : path.join(process.resourcesPath, 'assets', 'tray.png');
|
||||
const iconPath = isDevelopment ? path.join(__dirname, '../../assets/tray.png') : path.join(process.resourcesPath, 'assets', 'tray.png');
|
||||
const tray = new Tray(iconPath);
|
||||
tray.setToolTip('中国电信-工作台');
|
||||
tray.setContextMenu(contextMenu);
|
||||
|
@ -4,36 +4,63 @@
|
||||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
// 打开新标签页
|
||||
/**
|
||||
* 在新标签页打开URL
|
||||
* @param callback 回调函数,参数为webContentId和url。其中webContentId是请求打开URL的webview的id。
|
||||
*/
|
||||
onOpenTab: (callback: (webContentId: number, url: string) => void) => {
|
||||
ipcRenderer.on('webview-new-window', (_event, webContentId, url) => callback(webContentId, url));
|
||||
},
|
||||
|
||||
// 获取当前屏幕的缩放比例和分辨率
|
||||
getPrimaryDisplay: () => ipcRenderer.invoke('get-primary-display'),
|
||||
/**
|
||||
* 获取当前屏幕的缩放比例和分辨率
|
||||
* @returns 缩放比例和分辨率
|
||||
*/
|
||||
getPrimaryDisplay: () => ipcRenderer.invoke('get-primary-display') as Promise<Electron.Display>,
|
||||
|
||||
// 检查URL是否可用
|
||||
/**
|
||||
* 检查URL是否可用
|
||||
* @param url 要检查的URL
|
||||
* @returns 是否可用
|
||||
*/
|
||||
checkUrlAvailable: (url: string) => ipcRenderer.invoke('check-url-available', url),
|
||||
|
||||
// 设置webview的cookie
|
||||
/**
|
||||
* 设置webview的cookie
|
||||
* @param url 要设置cookie的URL
|
||||
* @param cookie cookie字符串
|
||||
*/
|
||||
setWebviewCookie: (url: string, cookie: string) => ipcRenderer.invoke('set-webview-cookie', url, cookie),
|
||||
|
||||
// 设置 sessionStorage
|
||||
/**
|
||||
* 按键将值设置到sessionStorage
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
setSessionStorage: (key: string, value: string) => {
|
||||
window.sessionStorage.setItem(key, value);
|
||||
},
|
||||
|
||||
// 获取 sessionStorage
|
||||
/**
|
||||
* 从sessionStorage中获取指定键的值
|
||||
* @param key 键
|
||||
* @returns 值
|
||||
*/
|
||||
getSessionStorage: (key: string) => {
|
||||
return window.sessionStorage.getItem(key);
|
||||
},
|
||||
|
||||
// 删除 sessionStorage
|
||||
/**
|
||||
* 从sessionStorage中删除指定键的值
|
||||
* @param key 键
|
||||
*/
|
||||
removeSessionStorage: (key: string) => {
|
||||
window.sessionStorage.removeItem(key);
|
||||
},
|
||||
|
||||
// 清空 sessionStorage
|
||||
/**
|
||||
* 清空sessionStorage
|
||||
*/
|
||||
clearSessionStorage: () => {
|
||||
window.sessionStorage.clear();
|
||||
}
|
||||
|
35
src/types/electron.d.ts
vendored
35
src/types/electron.d.ts
vendored
@ -1,11 +1,46 @@
|
||||
export interface ElectronAPI {
|
||||
/**
|
||||
* 在新标签页打开URL
|
||||
* @param callback 回调函数,参数为webContentId和url。其中webContentId是请求打开URL的webview的id。
|
||||
*/
|
||||
onOpenTab: (callback: (webContentId: number, url: string) => void) => void;
|
||||
/**
|
||||
* 获取当前屏幕的缩放比例和分辨率
|
||||
* @returns 缩放比例和分辨率
|
||||
*/
|
||||
getPrimaryDisplay: () => Promise<Electron.Display>;
|
||||
/**
|
||||
* 检查URL是否可用
|
||||
* @param url 要检查的URL
|
||||
* @returns 是否可用
|
||||
*/
|
||||
checkUrlAvailable: (url: string) => Promise<{ ok: boolean; status: number; error?: string }>;
|
||||
/**
|
||||
* 设置webview的cookie
|
||||
* @param url 要设置cookie的URL
|
||||
* @param cookie cookie字符串
|
||||
*/
|
||||
setWebviewCookie: (url: string, cookie: string) => Promise<boolean>;
|
||||
/**
|
||||
* 按键将值设置到sessionStorage
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
setSessionStorage: (key: string, value: string) => void;
|
||||
/**
|
||||
* 从sessionStorage中获取指定键的值
|
||||
* @param key 键
|
||||
* @returns 值
|
||||
*/
|
||||
getSessionStorage: (key: string) => string | null;
|
||||
/**
|
||||
* 从sessionStorage中删除指定键的值
|
||||
* @param key 键
|
||||
*/
|
||||
removeSessionStorage: (key: string) => void;
|
||||
/**
|
||||
* 清空sessionStorage
|
||||
*/
|
||||
clearSessionStorage: () => void;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user