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

use IPC bridge for fs relating to responses #8311

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 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
12 changes: 4 additions & 8 deletions packages/insomnia-sdk/src/objects/response.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Ajv from 'ajv';
import deepEqual from 'deep-equal';
import fs from 'fs';
import { RESPONSE_CODE_REASONS } from 'insomnia/src/common/constants';
import { readCurlResponse } from 'insomnia/src/models/response';
import type { sendCurlAndWriteTimelineError, sendCurlAndWriteTimelineResponse } from 'insomnia/src/network/network';

import { Cookie, type CookieOptions } from './cookies';
Expand Down Expand Up @@ -318,14 +318,10 @@ export async function readBodyFromPath(response: sendCurlAndWriteTimelineRespons
} else if (!response.bodyPath) {
return '';
}
const nodejsReadCurlResponse = process.type === 'renderer' ? window.bridge.readCurlResponse : readCurlResponse;
const nodejsReadCurlResponse = process.type === 'renderer' ? window.bridge.readFile : ({ path }: { path: string }) => fs.promises.readFile(path, 'utf8');
const readResponseResult = await nodejsReadCurlResponse({
bodyPath: response.bodyPath,
bodyCompression: response.bodyCompression,
path: response.bodyPath,
});

if (readResponseResult.error) {
throw Error(`Failed to read body: ${readResponseResult.error}`);
}
return readResponseResult.body;
return readResponseResult;
}
13 changes: 5 additions & 8 deletions packages/insomnia-sdk/src/objects/send-request.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from 'fs';
import type { CurlRequestOutput } from 'insomnia/src/main/network/libcurl-promise';
import { readCurlResponse } from 'insomnia/src/models/response';
import type { Settings } from 'insomnia/src/models/settings';
import { Cookie } from 'tough-cookie';
import { v4 as uuidv4 } from 'uuid';
Expand Down Expand Up @@ -259,20 +259,17 @@ async function curlOutputToResponse(
originalRequest,
});
}
const nodejsReadCurlResponse = process.type === 'renderer' ? window.bridge.readCurlResponse : readCurlResponse;
const nodejsReadCurlResponse = process.type === 'renderer' ? window.bridge.readFile : ({ path }: { path: string }) => fs.promises.readFile(path, 'utf8');
const bodyResult = await nodejsReadCurlResponse({
bodyPath: result.responseBodyPath,
bodyCompression: result.patch.bodyCompression,
path: result.responseBodyPath,
});
if (bodyResult.error) {
throw Error(bodyResult.error);
}

return new Response({
code: lastRedirect.code,
reason: lastRedirect.reason,
header: headers,
cookie: cookies as CookieOptions[],
body: bodyResult.body,
body: bodyResult,
// stream is always undefined
// because it is inaccurate to differentiate if body is binary
stream: undefined,
Expand Down
6 changes: 3 additions & 3 deletions packages/insomnia/src/common/har.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export async function exportHarResponse(response: Response | null) {
httpVersion: 'HTTP/1.1',
cookies: getResponseCookies(response),
headers: getResponseHeaders(response),
content: getResponseContent(response),
content: await getResponseContent(response),
redirectURL: '',
headersSize: -1,
bodySize: -1,
Expand Down Expand Up @@ -343,8 +343,8 @@ function mapCookie(cookie: ToughCookie) {
return harCookie;
}

function getResponseContent(response: Response) {
let body = models.response.getBodyBuffer(response);
async function getResponseContent(response: Response) {
let body = response.bodyPath && await fs.promises.readFile(response.bodyPath);

if (body === null) {
body = Buffer.alloc(0);
Expand Down
4 changes: 1 addition & 3 deletions packages/insomnia/src/common/send-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import * as models from '../models';
import type { Environment, UserUploadEnvironment } from '../models/environment';
import type { Request } from '../models/request';
import type { RequestGroup } from '../models/request-group';
import { getBodyBuffer } from '../models/response';
import type { Settings } from '../models/settings';
import { isWorkspace, type Workspace } from '../models/workspace';
import {
Expand Down Expand Up @@ -172,8 +171,7 @@ export async function getSendRequestCallbackMemDb(environmentId: string, memDB:
const { statusCode: status, statusMessage, headers: headerArray, elapsedTime: responseTime } = res;

const headers = headerArray?.reduce((acc, { name, value }) => ({ ...acc, [name.toLowerCase() || '']: value || '' }), []);
const bodyBuffer = await getBodyBuffer(res) as Buffer;
const data = bodyBuffer ? bodyBuffer.toString('utf8') : undefined;
const data = res.bodyPath && await fs.readFile(res.bodyPath, 'utf8');

const testResults = [...(mutatedContext.requestTestResults || []), ...(postMutatedContext.requestTestResults || [])];
return {
Expand Down
5 changes: 2 additions & 3 deletions packages/insomnia/src/hidden-window-preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import * as fs from 'node:fs';
import { contextBridge, ipcRenderer, type IpcRendererEvent } from 'electron';
import { asyncTasksAllSettled, OriginalPromise, ProxiedPromise, type RequestContext, resetAsyncTasks, stopMonitorAsyncTasks } from 'insomnia-sdk';

import type { Compression } from './models/response';
// this will also import lots of node_modules into the preload script, consider moving this file insomnia-sdk
import { requireInterceptor } from './requireInterceptor';

export interface HiddenBrowserWindowToMainBridgeAPI {
requireInterceptor: (module: string) => any;
onmessage: (listener: (data: any, callback: (result: any) => void) => void) => void;
curlRequest: (options: any) => Promise<any>;
readCurlResponse: (options: { bodyPath: string; bodyCompression: Compression }) => Promise<{ body: string; error: string }>;
readFile: (options: { path: string }) => Promise<string>;
setBusy: (busy: boolean) => void;
appendFile: (logPath: string, logContent: string) => Promise<void>;
asyncTasksAllSettled: () => Promise<void>;
Expand All @@ -36,7 +35,7 @@ const bridge: HiddenBrowserWindowToMainBridgeAPI = {
},
requireInterceptor,
curlRequest: options => ipcRenderer.invoke('curlRequest', options),
readCurlResponse: options => ipcRenderer.invoke('readCurlResponse', options),
readFile: options => ipcRenderer.invoke('readFile', options),
setBusy: busy => ipcRenderer.send('set-hidden-window-busy-status', busy),
// TODO: following methods are for simulating current behavior of running async tasks
// in the future, it should be better to keep standard way of handling async tasks to avoid confusion
Expand Down
1 change: 1 addition & 0 deletions packages/insomnia/src/main/ipc/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export type HandleChannels =
| 'installPlugin'
| 'open-channel-to-hidden-browser-window'
| 'readCurlResponse'
| 'readFile'
| 'restoreBackup'
| 'showOpenDialog'
| 'showSaveDialog'
Expand Down
14 changes: 8 additions & 6 deletions packages/insomnia/src/main/ipc/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface RendererToMainBridgeAPI {
setMenuBarVisibility: (visible: boolean) => void;
installPlugin: typeof installPlugin;
writeFile: (options: { path: string; content: string }) => Promise<string>;
readFile: (options: { path: string }) => Promise<string>;
cancelCurlRequest: typeof cancelCurlRequest;
curlRequest: typeof curlRequest;
on: (channel: RendererOnChannels, listener: (event: IpcRendererEvent, ...args: any[]) => void) => () => void;
Expand Down Expand Up @@ -90,12 +91,13 @@ export function registerMainHandlers() {
});

ipcMainHandle('writeFile', async (_, options: { path: string; content: string }) => {
try {
await fs.promises.writeFile(options.path, options.content);
return options.path;
} catch (err) {
throw new Error(err);
}
await fs.promises.writeFile(options.path, options.content);
return options.path;
});

ipcMainHandle('readFile', async (_, options: { path: string }) => {
const content = await fs.promises.readFile(options.path, 'utf-8');
return content;
});

ipcMainHandle('curlRequest', (_, options: Parameters<typeof curlRequest>[0]) => {
Expand Down
2 changes: 0 additions & 2 deletions packages/insomnia/src/main/network/curl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import type { CookieJar } from '../../models/cookie-jar';
import type { Environment } from '../../models/environment';
import type { RequestAuthentication, RequestHeader } from '../../models/request';
import type { Response } from '../../models/response';
import { readCurlResponse } from '../../models/response';
import { filterClientCertificates } from '../../network/certificate';
import { addSetCookiesToToughCookieJar } from '../../network/set-cookie-util';
import { invariant } from '../../utils/invariant';
Expand Down Expand Up @@ -378,7 +377,6 @@ export const registerCurlHandlers = () => {
ipcMainOn('curl.closeAll', closeAllCurlConnections);
ipcMainHandle('curl.readyState', (_, options: Parameters<typeof getCurlReadyState>[0]) => getCurlReadyState(options));
ipcMainHandle('curl.event.findMany', (_, options: Parameters<typeof findMany>[0]) => findMany(options));
ipcMainHandle('readCurlResponse', (_, options: Parameters<typeof readCurlResponse>[0]) => readCurlResponse(options));
};

electron.app.on('window-all-closed', closeAllCurlConnections);
22 changes: 4 additions & 18 deletions packages/insomnia/src/models/__tests__/response.test.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
import fs from 'fs';
import { tmpdir } from 'os';
import path from 'path';
import { describe, expect, it } from 'vitest';
import zlib from 'zlib';

import * as models from '../../models';
import { Response } from '../response';

describe('migrate()', () => {

it('does it', async () => {
const bodyPath = path.join(tmpdir(), 'foo.zip');
fs.writeFileSync(bodyPath, zlib.gzipSync('Hello World!'));
const response = await models.initModel(models.response.type, {
bodyPath,
});
const body = await models.response.getBodyBuffer(response).toString();
expect(response.bodyCompression).toBe('zip');
expect(body).toBe('Hello World!');
});

it('migrates leaves bodyCompression for null', async () => {
expect(
(
await models.initModel(models.response.type, {
bodyPath: '/foo/bar',
bodyCompression: null,
})
}) as Response
).bodyCompression,
).toBe(null);
});
Expand All @@ -35,7 +21,7 @@ describe('migrate()', () => {
(
await models.initModel(models.response.type, {
bodyPath: '/foo/bar',
})
}) as Response
).bodyCompression,
).toBe('zip');
});
Expand All @@ -46,7 +32,7 @@ describe('migrate()', () => {
await models.initModel(models.response.type, {
bodyPath: '/foo/bar',
bodyCompression: 'zip',
})
}) as Response
).bodyCompression,
).toBe('zip');
});
Expand Down
36 changes: 0 additions & 36 deletions packages/insomnia/src/models/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,42 +230,6 @@ export const getBodyStream = (
return fs.createReadStream(response?.bodyPath);
}
};
export const readCurlResponse = async (options: { bodyPath?: string; bodyCompression?: Compression }) => {
const readFailureMsg = '[main/curlBridgeAPI] failed to read response body message';
const bodyBufferOrErrMsg = getBodyBuffer(options, readFailureMsg);
// TODO(jackkav): simplify the fail msg and reuse in other getBodyBuffer renderer calls

if (!bodyBufferOrErrMsg) {
return { body: '', error: readFailureMsg };
} else if (typeof bodyBufferOrErrMsg === 'string') {
if (bodyBufferOrErrMsg === readFailureMsg) {
return { body: '', error: readFailureMsg };
}
return { body: '', error: `unknown error in loading response body: ${bodyBufferOrErrMsg}` };
}

return { body: bodyBufferOrErrMsg.toString('utf8'), error: '' };
};
export const getBodyBuffer = (
response?: { bodyPath?: string; bodyCompression?: Compression },
readFailureValue?: string,
): Buffer | string | null => {
if (!response?.bodyPath) {
// No body, so return empty Buffer
return Buffer.alloc(0);
}
try {
const rawBuffer = fs.readFileSync(response?.bodyPath);
if (response?.bodyCompression === 'zip') {
return zlib.gunzipSync(rawBuffer);
} else {
return rawBuffer;
}
} catch (err) {
console.warn('Failed to read response body', err.message);
return readFailureValue === undefined ? null : readFailureValue;
}
};
Comment on lines -233 to -268
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🫡


export function getTimeline(response: Response, showBody?: boolean) {
const { timelinePath, bodyPath } = response;
Expand Down
43 changes: 22 additions & 21 deletions packages/insomnia/src/network/__tests__/network.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -182,8 +182,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -286,8 +286,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -350,8 +350,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -434,8 +434,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -499,8 +499,7 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));
expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -543,8 +542,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -586,8 +585,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -630,8 +629,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -735,8 +734,8 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
const bodyBuffer = models.response.getBodyBuffer(response);
const body = JSON.parse(String(bodyBuffer));
const body = JSON.parse(fs.readFileSync(response.bodyPath, 'utf8'));

expect(body).toEqual({
meta: {},
features: {
Expand Down Expand Up @@ -790,7 +789,9 @@ describe('sendCurlAndWriteTimeline()', () => {
'/tmp/res_id',
'res_id'
);
expect(JSON.parse(String(models.response.getBodyBuffer(responseV1))).options.HTTP_VERSION).toBe('V1_0');
const body = JSON.parse(fs.readFileSync(responseV1.bodyPath, 'utf8'));

expect(body.options.HTTP_VERSION).toBe('V1_0');
expect(getHttpVersion(HttpVersions.V1_0).curlHttpVersion).toBe(CurlHttpVersion.V1_0);
expect(getHttpVersion(HttpVersions.V1_1).curlHttpVersion).toBe(CurlHttpVersion.V1_1);
expect(getHttpVersion(HttpVersions.V2PriorKnowledge).curlHttpVersion).toBe(CurlHttpVersion.V2PriorKnowledge);
Expand Down
Loading
Loading