Use electron fetch API.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg
2023-09-13 18:59:30 -07:00
parent d2de965106
commit f8758fa303
5 changed files with 30 additions and 90 deletions

View File

@@ -1,7 +1,6 @@
import type {Session} from "electron/main"; import type {Session} from "electron/main";
import {Notification, app, net} from "electron/main"; import {Notification, app} from "electron/main";
import getStream from "get-stream";
import * as semver from "semver"; import * as semver from "semver";
import {z} from "zod"; import {z} from "zod";
@@ -9,7 +8,6 @@ import * as ConfigUtil from "../common/config-util.js";
import Logger from "../common/logger-util.js"; import Logger from "../common/logger-util.js";
import * as LinuxUpdateUtil from "./linux-update-util.js"; import * as LinuxUpdateUtil from "./linux-update-util.js";
import {fetchResponse} from "./request.js";
const logger = new Logger({ const logger = new Logger({
file: "linux-update-util.log", file: "linux-update-util.log",
@@ -20,13 +18,13 @@ export async function linuxUpdateNotification(session: Session): Promise<void> {
url = ConfigUtil.getConfigItem("betaUpdate", false) ? url : url + "/latest"; url = ConfigUtil.getConfigItem("betaUpdate", false) ? url : url + "/latest";
try { try {
const response = await fetchResponse(net.request({url, session})); const response = await session.fetch(url);
if (response.statusCode !== 200) { if (!response.ok) {
logger.log("Linux update response status: ", response.statusCode); logger.log("Linux update response status: ", response.status);
return; return;
} }
const data: unknown = JSON.parse(await getStream(response)); const data: unknown = await response.json();
/* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/naming-convention */
const latestVersion = ConfigUtil.getConfigItem("betaUpdate", false) const latestVersion = ConfigUtil.getConfigItem("betaUpdate", false)
? z.array(z.object({tag_name: z.string()})).parse(data)[0].tag_name ? z.array(z.object({tag_name: z.string()})).parse(data)[0].tag_name

View File

@@ -1,33 +1,18 @@
import type {ClientRequest, IncomingMessage, Session} from "electron/main"; import type {Session} from "electron/main";
import {app, net} from "electron/main"; import {app} from "electron/main";
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import stream from "node:stream"; import {Readable} from "node:stream";
import util from "node:util"; import {pipeline} from "node:stream/promises";
import type {ReadableStream} from "node:stream/web";
import * as Sentry from "@sentry/electron"; import * as Sentry from "@sentry/electron";
import getStream from "get-stream";
import {z} from "zod"; import {z} from "zod";
import Logger from "../common/logger-util.js"; import Logger from "../common/logger-util.js";
import * as Messages from "../common/messages.js"; import * as Messages from "../common/messages.js";
import type {ServerConf} from "../common/types.js"; import type {ServerConf} from "../common/types.js";
export async function fetchResponse(
request: ClientRequest,
): Promise<IncomingMessage> {
return new Promise((resolve, reject) => {
request.on("response", resolve);
request.on("abort", () => {
reject(new Error("Request aborted"));
});
request.on("error", reject);
request.end();
});
}
const pipeline = util.promisify(stream.pipeline);
/* Request: domain-util */ /* Request: domain-util */
const logger = new Logger({ const logger = new Logger({
@@ -59,17 +44,12 @@ export const _getServerSettings = async (
domain: string, domain: string,
session: Session, session: Session,
): Promise<ServerConf> => { ): Promise<ServerConf> => {
const response = await fetchResponse( const response = await session.fetch(domain + "/api/v1/server_settings");
net.request({ if (!response.ok) {
url: domain + "/api/v1/server_settings",
session,
}),
);
if (response.statusCode !== 200) {
throw new Error(Messages.invalidZulipServerError(domain)); throw new Error(Messages.invalidZulipServerError(domain));
} }
const data: unknown = JSON.parse(await getStream(response)); const data: unknown = await response.json();
/* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/naming-convention */
const { const {
realm_name, realm_name,
@@ -104,14 +84,17 @@ export const _saveServerIcon = async (
session: Session, session: Session,
): Promise<string | null> => { ): Promise<string | null> => {
try { try {
const response = await fetchResponse(net.request({url, session})); const response = await session.fetch(url);
if (response.statusCode !== 200) { if (!response.ok) {
logger.log("Could not get server icon."); logger.log("Could not get server icon.");
return null; return null;
} }
const filePath = generateFilePath(url); const filePath = generateFilePath(url);
await pipeline(response, fs.createWriteStream(filePath)); await pipeline(
Readable.fromWeb(response.body as ReadableStream<Uint8Array>),
fs.createWriteStream(filePath),
);
return filePath; return filePath;
} catch (error: unknown) { } catch (error: unknown) {
logger.log("Could not get server icon."); logger.log("Could not get server icon.");
@@ -128,16 +111,10 @@ export const _isOnline = async (
session: Session, session: Session,
): Promise<boolean> => { ): Promise<boolean> => {
try { try {
const response = await fetchResponse( const response = await session.fetch(`${url}/api/v1/server_settings`, {
net.request({
method: "HEAD", method: "HEAD",
url: `${url}/api/v1/server_settings`, });
session, return response.ok;
}),
);
const isValidResponse =
response.statusCode >= 200 && response.statusCode < 400;
return isValidResponse;
} catch (error: unknown) { } catch (error: unknown) {
logger.log(error); logger.log(error);
return false; return false;

42
package-lock.json generated
View File

@@ -32,7 +32,6 @@
"electron-updater": "^6.1.4", "electron-updater": "^6.1.4",
"electron-window-state": "^5.0.3", "electron-window-state": "^5.0.3",
"escape-goat": "^4.0.0", "escape-goat": "^4.0.0",
"get-stream": "^8.0.1",
"htmlhint": "^1.1.2", "htmlhint": "^1.1.2",
"i18n": "^0.15.1", "i18n": "^0.15.1",
"iso-639-1": "^3.1.0", "iso-639-1": "^3.1.0",
@@ -2905,21 +2904,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/cacheable-request/node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dev": true,
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/call-bind": { "node_modules/call-bind": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
@@ -5336,21 +5320,6 @@
"@types/yauzl": "^2.9.1" "@types/yauzl": "^2.9.1"
} }
}, },
"node_modules/extract-zip/node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dev": true,
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/extsprintf": { "node_modules/extsprintf": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz",
@@ -5868,12 +5837,15 @@
} }
}, },
"node_modules/get-stream": { "node_modules/get-stream": {
"version": "8.0.1", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dev": true, "dev": true,
"dependencies": {
"pump": "^3.0.0"
},
"engines": { "engines": {
"node": ">=16" "node": ">=8"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"

View File

@@ -165,7 +165,6 @@
"electron-updater": "^6.1.4", "electron-updater": "^6.1.4",
"electron-window-state": "^5.0.3", "electron-window-state": "^5.0.3",
"escape-goat": "^4.0.0", "escape-goat": "^4.0.0",
"get-stream": "^8.0.1",
"htmlhint": "^1.1.2", "htmlhint": "^1.1.2",
"i18n": "^0.15.1", "i18n": "^0.15.1",
"iso-639-1": "^3.1.0", "iso-639-1": "^3.1.0",

6
typings.d.ts vendored
View File

@@ -1,9 +1,3 @@
declare namespace Electron {
// https://github.com/electron/typescript-definitions/issues/170
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface IncomingMessage extends NodeJS.ReadableStream {}
}
declare module "zulip:remote" { declare module "zulip:remote" {
export const { export const {
app, app,