mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
desktop: use net.fetch instead when handling protocol
This commit is contained in:
committed by
Abdullah Atta
parent
0f9e32b49f
commit
de50be9d1b
31
apps/desktop/global.d.ts
vendored
31
apps/desktop/global.d.ts
vendored
@@ -19,9 +19,40 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
/* eslint-disable no-var */
|
/* eslint-disable no-var */
|
||||||
|
|
||||||
import { BrowserWindow } from "electron";
|
import { BrowserWindow } from "electron";
|
||||||
|
import {
|
||||||
|
type FormData as FormDataType,
|
||||||
|
type Headers as HeadersType,
|
||||||
|
type Request as RequestType,
|
||||||
|
type Response as ResponseType
|
||||||
|
} from "undici";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
var window: BrowserWindow | null;
|
var window: BrowserWindow | null;
|
||||||
var RELEASE: boolean;
|
var RELEASE: boolean;
|
||||||
var MAC_APP_STORE: boolean;
|
var MAC_APP_STORE: boolean;
|
||||||
|
|
||||||
|
// Re-export undici fetch function and various classes to global scope.
|
||||||
|
// These are classes and functions expected to be at global scope according to Node.js v18 API
|
||||||
|
// documentation.
|
||||||
|
// See: https://nodejs.org/dist/latest-v18.x/docs/api/globals.html
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
export var {
|
||||||
|
FormData,
|
||||||
|
Headers,
|
||||||
|
Request,
|
||||||
|
Response,
|
||||||
|
fetch
|
||||||
|
}: typeof import("undici");
|
||||||
|
|
||||||
|
type FormData = FormDataType;
|
||||||
|
type Headers = HeadersType;
|
||||||
|
type Request = RequestType;
|
||||||
|
type Response = ResponseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: the import in the global block above needs to be a var for this to work properly.
|
||||||
|
globalThis.fetch = fetch;
|
||||||
|
globalThis.FormData = FormData;
|
||||||
|
globalThis.Headers = Headers;
|
||||||
|
globalThis.Request = Request;
|
||||||
|
globalThis.Response = Response;
|
||||||
|
|||||||
@@ -17,16 +17,14 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { protocol, ProtocolRequest } from "electron";
|
import { protocol, net } from "electron";
|
||||||
import { isDevelopment } from "./index";
|
import { isDevelopment } from "./index";
|
||||||
import { createReadStream } from "fs";
|
import { createReadStream } from "fs";
|
||||||
import { extname, normalize } from "path";
|
import { extname, normalize } from "path";
|
||||||
import { URL } from "url";
|
import { URL } from "url";
|
||||||
import fetch, { Response } from "node-fetch";
|
|
||||||
|
|
||||||
const BASE_PATH = isDevelopment() ? "../public" : "";
|
const BASE_PATH = isDevelopment() ? "../public" : "";
|
||||||
const HOSTNAME = `app.notesnook.com`;
|
const HOSTNAME = `app.notesnook.com`;
|
||||||
const FILE_NOT_FOUND = -6;
|
|
||||||
const SCHEME = "https";
|
const SCHEME = "https";
|
||||||
const extensionToMimeType: Record<string, string> = {
|
const extensionToMimeType: Record<string, string> = {
|
||||||
html: "text/html",
|
html: "text/html",
|
||||||
@@ -34,101 +32,47 @@ const extensionToMimeType: Record<string, string> = {
|
|||||||
js: "application/javascript",
|
js: "application/javascript",
|
||||||
css: "text/css",
|
css: "text/css",
|
||||||
svg: "image/svg+xml",
|
svg: "image/svg+xml",
|
||||||
png: "image/png"
|
png: "image/png",
|
||||||
|
jpg: "image/jpg",
|
||||||
|
ttf: "font/ttf",
|
||||||
|
woff: "font/woff",
|
||||||
|
woff2: "font/woff2"
|
||||||
};
|
};
|
||||||
|
|
||||||
function registerProtocol() {
|
function registerProtocol() {
|
||||||
const protocolInterceptionResult = protocol.interceptStreamProtocol(
|
protocol.handle(SCHEME, async (request) => {
|
||||||
SCHEME,
|
const url = new URL(request.url);
|
||||||
async (request, callback) => {
|
if (shouldInterceptRequest(url)) {
|
||||||
const url = new URL(request.url);
|
console.info("Intercepting request:", request.url);
|
||||||
if (shouldInterceptRequest(url)) {
|
const loadIndex = !extname(url.pathname);
|
||||||
console.info("Intercepting request:", request.url);
|
const filePath = normalize(
|
||||||
|
`${__dirname}${
|
||||||
const loadIndex = !extname(url.pathname);
|
loadIndex ? `${BASE_PATH}/index.html` : `${BASE_PATH}/${url.pathname}`
|
||||||
const filePath = normalize(
|
}`
|
||||||
`${__dirname}${
|
);
|
||||||
loadIndex
|
if (!filePath) {
|
||||||
? `${BASE_PATH}/index.html`
|
console.error("Local asset file not found at", filePath);
|
||||||
: `${BASE_PATH}/${url.pathname}`
|
return new Response(undefined, {
|
||||||
}`
|
status: 404,
|
||||||
);
|
statusText: "FILE_NOT_FOUND"
|
||||||
if (!filePath) {
|
|
||||||
console.error("Local asset file not found at", filePath);
|
|
||||||
callback({ error: FILE_NOT_FOUND });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const fileExtension = extname(filePath).replace(".", "");
|
|
||||||
|
|
||||||
const data = createReadStream(filePath);
|
|
||||||
callback({
|
|
||||||
data,
|
|
||||||
mimeType: extensionToMimeType[fileExtension]
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
let response: Response;
|
|
||||||
try {
|
|
||||||
const body = await getBody(request);
|
|
||||||
response = await fetch(request.url, {
|
|
||||||
...request,
|
|
||||||
body,
|
|
||||||
headers: {
|
|
||||||
...request.headers
|
|
||||||
// origin: `${PROTOCOL}://${HOSTNAME}/`
|
|
||||||
},
|
|
||||||
referrer: request.referrer,
|
|
||||||
redirect: "manual"
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
console.error(`Error sending request to `, request.url, "Error: ", e);
|
|
||||||
callback({ statusCode: 400 });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback({
|
|
||||||
statusCode: response.status,
|
|
||||||
data: response.body || undefined,
|
|
||||||
headers: Object.fromEntries(response.headers.entries()),
|
|
||||||
mimeType: response.headers.get("Content-Type") || undefined
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const fileExtension = extname(filePath).replace(".", "");
|
||||||
|
return new Response(createReadStream(filePath), {
|
||||||
|
headers: { "Content-Type": extensionToMimeType[fileExtension] }
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return net.fetch(request, {
|
||||||
|
bypassCustomProtocolHandlers: true
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
return Response.error();
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
|
console.info(`${SCHEME} protocol inteception "successful"`);
|
||||||
console.info(
|
|
||||||
`${SCHEME} protocol inteception ${
|
|
||||||
protocolInterceptionResult ? "successful" : "failed"
|
|
||||||
}.`
|
|
||||||
);
|
|
||||||
|
|
||||||
// protocol.handle(SCHEME, (request) => {
|
|
||||||
// const url = new URL(request.url);
|
|
||||||
// if (shouldInterceptRequest(url)) {
|
|
||||||
// console.info("Intercepting request:", request.url);
|
|
||||||
// const loadIndex = !extname(url.pathname);
|
|
||||||
// const absoluteFilePath = normalize(
|
|
||||||
// `${__dirname}${
|
|
||||||
// loadIndex ? `${BASE_PATH}/index.html` : `${BASE_PATH}/${url.pathname}`
|
|
||||||
// }`
|
|
||||||
// );
|
|
||||||
// const filePath = getPath(absoluteFilePath);
|
|
||||||
// if (!filePath) {
|
|
||||||
// console.error("Local asset file not found at", filePath);
|
|
||||||
// return new Response(undefined, {
|
|
||||||
// status: 404,
|
|
||||||
// statusText: "FILE_NOT_FOUND"
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// const fileExtension = extname(filePath).replace(".", "");
|
|
||||||
// const data = createReadStream(filePath);
|
|
||||||
// return new Response(data, {
|
|
||||||
// headers: { "Content-Type": extensionToMimeType[fileExtension] }
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// return net.fetch(request);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// console.info(`${SCHEME} protocol inteception "successful"`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bypassedRoutes: string[] = [];
|
const bypassedRoutes: string[] = [];
|
||||||
@@ -139,22 +83,3 @@ function shouldInterceptRequest(url: URL) {
|
|||||||
|
|
||||||
const PROTOCOL_URL = `${SCHEME}://${HOSTNAME}/`;
|
const PROTOCOL_URL = `${SCHEME}://${HOSTNAME}/`;
|
||||||
export { registerProtocol, PROTOCOL_URL };
|
export { registerProtocol, PROTOCOL_URL };
|
||||||
|
|
||||||
async function getBody(request: ProtocolRequest) {
|
|
||||||
const session = globalThis?.window?.webContents?.session;
|
|
||||||
|
|
||||||
const blobParts = [];
|
|
||||||
if (!request.uploadData || !request.uploadData.length) return null;
|
|
||||||
for (const data of request.uploadData) {
|
|
||||||
if (data.bytes) {
|
|
||||||
blobParts.push(new Uint8Array(data.bytes));
|
|
||||||
} else if (session && data.blobUUID) {
|
|
||||||
const buffer = await session.getBlobData(data.blobUUID);
|
|
||||||
if (!buffer) continue;
|
|
||||||
blobParts.push(new Uint8Array(buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const blob = new Blob(blobParts);
|
|
||||||
return blob;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user