Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed the issue that the TCP connection was interrupted when setting a proxy #9708

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions app/electron/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ app.whenReady().then(() => {
event.sender.send("siyuan-event", "leave-full-screen");
});
});
ipcMain.on("siyuan-cmd", (event, data) => {
ipcMain.on("siyuan-cmd", async (event, data) => {
let cmd = data;
let webContentsId = event.sender.id;
if (typeof data !== "string") {
Expand Down Expand Up @@ -820,17 +820,29 @@ app.whenReady().then(() => {
}
break;
case "setProxy":
event.sender.session.closeAllConnections().then(() => {
try {
let proxy, log;
if (data.proxyURL.startsWith("://")) {
event.sender.session.setProxy({mode: "system"}).then(() => {
console.log("network proxy [system]");
});
return;
proxy = {mode: "system"};
log = "network proxy [system]";
} else {
proxy = {proxyRules: data.proxyURL};
log = `network proxy [${data.proxyURL}]`;
}
event.sender.session.setProxy({proxyRules: data.proxyURL}).then(() => {
console.log("network proxy [" + data.proxyURL + "]");
await event.sender.session.closeAllConnections();
await event.sender.session.setProxy(proxy);
console.log(log);
event.reply("siyuan-proxy-reply", {
state: "fulfilled",
proxy,
});
});
} catch (error) {
event.reply("siyuan-proxy-reply", {
state: "rejected",
proxy,
error,
});
}
break;
}
});
Expand Down
2 changes: 0 additions & 2 deletions app/src/boot/onGetConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {showMessage} from "../dialog/message";
import {replaceLocalPath} from "../editor/rename";
import {setTabPosition} from "../window/setHeader";
import {initBar} from "../layout/topBar";
import {setProxy} from "../config/util/about";
import {openChangelog} from "./openChangelog";
import {getIdFromSYProtocol, isSYProtocol} from "../util/pathName";
import {App} from "../index";
Expand Down Expand Up @@ -135,7 +134,6 @@ export const onGetConfig = (isStart: boolean, app: App) => {
}
});
initBar(app);
setProxy();
initStatus();
initWindow(app);
appearance.onSetappearance(window.siyuan.config.appearance);
Expand Down
25 changes: 22 additions & 3 deletions app/src/config/util/about.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,28 @@ import {Constants} from "../../constants";

export const setProxy = () => {
/// #if !BROWSER
ipcRenderer.send(Constants.SIYUAN_CMD, {
cmd: "setProxy",
proxyURL: `${window.siyuan.config.system.networkProxy.scheme}://${window.siyuan.config.system.networkProxy.host}:${window.siyuan.config.system.networkProxy.port}`
return new Promise((resolve, reject) => {
ipcRenderer.once(Constants.SIYUAN_PROXY_REPLY, (event, data: {
state: "fulfilled" | "rejected",
proxy: {mode: "system"} | {proxyRules: string},
error?: any,
}) => {
switch (data.state) {
case "fulfilled":
resolve(data.proxy);
break;
case "rejected":
reject(data.error);
break;
default:
reject(new Error(`Unknown state: ${data.state}`));
break;
}
});
ipcRenderer.send(Constants.SIYUAN_CMD, {
cmd: "setProxy",
proxyURL: `${window.siyuan.config.system.networkProxy.scheme}://${window.siyuan.config.system.networkProxy.host}:${window.siyuan.config.system.networkProxy.port}`
});
});
/// #endif
};
Expand Down
2 changes: 2 additions & 0 deletions app/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export abstract class Constants {
public static readonly SIYUAN_GET: string = "siyuan-get";
public static readonly SIYUAN_EVENT: string = "siyuan-event";

public static readonly SIYUAN_PROXY_REPLY: string = "siyuan-proxy-reply";

public static readonly SIYUAN_CONFIG_TRAY: string = "siyuan-config-tray";
public static readonly SIYUAN_QUIT: string = "siyuan-quit";
public static readonly SIYUAN_HOTKEY: string = "siyuan-hotkey";
Expand Down
24 changes: 16 additions & 8 deletions app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import {Model} from "./layout/Model";
import {onGetConfig} from "./boot/onGetConfig";
import {initBlockPopover} from "./block/popover";
import {account} from "./config/account";
import {setProxy} from "./config/util/about";
import {addScript, addScriptSync} from "./protyle/util/addScript";
import {genUUID} from "./util/genID";
import {fetchGet, fetchPost} from "./util/fetch";
import {addBaseURL, getIdFromSYProtocol, isSYProtocol, setNoteBook} from "./util/pathName";
import {registerServiceWorker} from "./util/serviceWorker";
import {registerServiceWorker, unregisterServiceWorker} from "./util/serviceWorker";
import {openFileById} from "./editor/util";
import {
bootSync,
Expand All @@ -33,11 +34,6 @@ export class App {
public appId: string;

constructor() {
/// #if BROWSER
registerServiceWorker(`${Constants.SERVICE_WORKER_PATH}?v=${Constants.SIYUAN_VERSION}`);
/// #endif
addScriptSync(`${Constants.PROTYLE_CDN}/js/lute/lute.min.js?v=${Constants.SIYUAN_VERSION}`, "protyleLuteScript");
addScript(`${Constants.PROTYLE_CDN}/js/protyle-html.js?v=${Constants.SIYUAN_VERSION}`, "protyleWcHtmlScript");
addBaseURL();

this.appId = Constants.SIYUAN_APPID;
Expand Down Expand Up @@ -161,6 +157,20 @@ export class App {
data: response.data.conf.uiLayout.bottom
};
}

await setProxy();

/// #if BROWSER
await registerServiceWorker();
/// #else
await unregisterServiceWorker();
/// #endif
addScriptSync(`${Constants.PROTYLE_CDN}/js/lute/lute.min.js?v=${Constants.SIYUAN_VERSION}`, "protyleLuteScript");
addScript(`${Constants.PROTYLE_CDN}/js/protyle-html.js?v=${Constants.SIYUAN_VERSION}`, "protyleWcHtmlScript");

setNoteBook();
initBlockPopover(this);

await loadPlugins(this);
getLocalStorage(() => {
fetchGet(`/appearance/langs/${window.siyuan.config.appearance.lang}.json?v=${Constants.SIYUAN_VERSION}`, (lauguages) => {
Expand All @@ -177,8 +187,6 @@ export class App {
});
});
});
setNoteBook();
initBlockPopover(this);
}
}

Expand Down
19 changes: 13 additions & 6 deletions app/src/mobile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {getCurrentEditor, openMobileFileById} from "./editor";
import {getSearch} from "../util/functions";
import {initRightMenu} from "./menu";
import {openChangelog} from "../boot/openChangelog";
import {registerServiceWorker} from "../util/serviceWorker";
import {registerServiceWorker, unregisterServiceWorker} from "../util/serviceWorker";
import {afterLoadPlugin, loadPlugins} from "../plugin/loader";
import {saveScroll} from "../protyle/scroll/saveScroll";
import {removeBlock} from "../protyle/wysiwyg/remove";
Expand All @@ -32,12 +32,8 @@ class App {
public appId: string;

constructor() {
if (!window.webkit?.messageHandlers && !window.JSAndroid) {
registerServiceWorker(`${Constants.SERVICE_WORKER_PATH}?v=${Constants.SIYUAN_VERSION}`);
}
addScriptSync(`${Constants.PROTYLE_CDN}/js/lute/lute.min.js?v=${Constants.SIYUAN_VERSION}`, "protyleLuteScript");
addScript(`${Constants.PROTYLE_CDN}/js/protyle-html.js?v=${Constants.SIYUAN_VERSION}`, "protyleWcHtmlScript");
addBaseURL();

this.appId = Constants.SIYUAN_APPID;
window.siyuan = {
zIndex: 10,
Expand All @@ -60,6 +56,7 @@ class App {
}
})
};

// 不能使用 touchstart,否则会被 event.stopImmediatePropagation() 阻塞
window.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => {
if (!window.siyuan.menus.menu.element.contains(event.target) && !hasClosestByAttribute(event.target, "data-menu", "true")) {
Expand All @@ -80,9 +77,19 @@ class App {
window.addEventListener("pagehide", () => {
saveScroll(window.siyuan.mobile.editor.protyle);
}, false);

fetchPost("/api/system/getConf", {}, async (confResponse) => {
confResponse.data.conf.keymap = Constants.SIYUAN_KEYMAP;
window.siyuan.config = confResponse.data.conf;

if (!window.webkit?.messageHandlers && !window.JSAndroid) {
await registerServiceWorker();
} else {
await unregisterServiceWorker();
}
addScriptSync(`${Constants.PROTYLE_CDN}/js/lute/lute.min.js?v=${Constants.SIYUAN_VERSION}`, "protyleLuteScript");
addScript(`${Constants.PROTYLE_CDN}/js/protyle-html.js?v=${Constants.SIYUAN_VERSION}`, "protyleWcHtmlScript");

await loadPlugins(this);
getLocalStorage(() => {
fetchGet(`/appearance/langs/${window.siyuan.config.appearance.lang}.json?v=${Constants.SIYUAN_VERSION}`, (lauguages) => {
Expand Down
105 changes: 91 additions & 14 deletions app/src/util/serviceWorker.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,94 @@
import { Constants } from "../constants";

const pathname = `${Constants.SERVICE_WORKER_PATH}?v=${Constants.SIYUAN_VERSION}`;

// https://github.com/siyuan-note/siyuan/pull/8012
export const registerServiceWorker = (scriptURL: string, scope = "/", workerType: WorkerType = "module") => {
if (!("serviceWorker" in navigator) || typeof (navigator.serviceWorker) === "undefined" ||
!("caches" in window) || !("fetch" in window)) {
return;
export const registerServiceWorker = async (
scirpt: string | URL = pathname,
scope: string = "/",
workerType: WorkerType = "module",
) => {
if (("serviceWorker" in window.navigator) && ("caches" in window) && ("fetch" in window)) {
try {
// REF https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration
const registration = await window.navigator.serviceWorker.register(scirpt, {
scope,
type: workerType,
});
await registration.update();
return true;
} catch (error) {
console.warn(`Registration service worker failed with ${error}`);
}
}
// REF https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration
window.navigator.serviceWorker
.register(scriptURL, {
scope,
type: workerType,
}).then(registration => {
registration.update();
}).catch(e => {
console.debug(`Registration failed with ${e}`);
});
return false;
};

export const unregisterServiceWorker = async (
scirpt: string | URL = pathname,
scope: string = "/",
) => {
if ("serviceWorker" in window.navigator) {
try {
const scriptURL = new URL(scirpt, window.document.baseURI);
const scopeURL = new URL(scope, window.document.baseURI);

const registration = await window.navigator.serviceWorker.getRegistration(scope);
if (isTargetRegistration(scriptURL, scopeURL, registration)) {
const result = await registration.unregister();
console.debug(`Unregistration service worker ${result ? "succeeded" : "failed"}`);
return result;
}
} catch (error) {
console.warn(`Unregistration service worker failed with ${error}`);
}
}
return false;
}

/* ❗加载同一个 worker 时不会触发 */
export const disableServiceWorker = (
scirpt: string | URL = pathname,
scope: string = "/",
) => {
if ("serviceWorker" in window.navigator) {
try {
const scriptURL = new URL(scirpt, window.document.baseURI);
const scopeURL = new URL(scope, window.document.baseURI);

const listener = async (e: Event) => {
console.debug(e);
const container = e.target as ServiceWorkerContainer;
const controllerScriptURL = new URL(container.controller.scriptURL);
if (scriptURL.pathname === controllerScriptURL.pathname) {
const registration = await container.ready;
if (isTargetRegistration(scriptURL, scopeURL, registration)) {
const result = await registration.unregister();
console.debug(`Auto unregistration service worker ${result ? "succeeded" : "failed"}`);
}
}
};
window.navigator.serviceWorker.addEventListener("controllerchange", listener);
return () => window.navigator.serviceWorker.removeEventListener("controllerchange", listener);
} catch (error) {
}
}
return () => {};
}

const isTargetRegistration = (
scriptURL: URL,
scopeURL: URL,
registration: ServiceWorkerRegistration,
) => {
try {
if (registration?.active?.scriptURL && registration?.scope) {
const registrationScriptURL = new URL(registration.active.scriptURL);
const registrationScopeURL = new URL(registration.scope);
return scriptURL.pathname === registrationScriptURL.pathname
&& scopeURL.pathname === registrationScopeURL.pathname;
}
} catch (error) {
}
return false
}