feat: add net module to utility process (#40017)
* chore: initial prototype of net api from utility process * chore: update url loader to work on both browser and utility processes * chore: add net files to utility process bundle * chore: re-add app ready check but only on main process * chore: replace browser thread dcheck's with sequence checker * refactor: move url loader from browser to common * refactor: move net-client-request.ts from browser to common * docs: add utility process to net api docs * refactor: move net module app ready check to browser only * refactor: switch import from main to common after moving to common * test: add basic net module test for utility process * refactor: switch browser pid with utility pid * refactor: move electron_api_net from browser to common * chore: add fetch to utility net module * chore: add isOnline and online to utility net module * refactor: move net spec helpers into helper file * refactor: break apart net module tests Adds two additional net module test files: `api-net-session-spec.ts` for tests that depend on a session being available (aka depend on running on the main process) and `api-net-custom-protocols-spec.ts` for custom protocol tests. This enables running `api-net-spec.ts` in the utility process. * test: add utility process mocha runner to run net module tests * docs: add utility process to net module classes * refactor: update imports in lib/utility to use electron/utility * chore: check browser context before using in main process Since the browser context supplied to the SimpleURLLoaderWrapper can now be null for use in the UtilityProcess, adding a null check for the main process before use to get a more sensible error if something goes wrong. Co-authored-by: Cheng Zhao <github@zcbenz.com> * chore: remove test debugging * chore: remove unnecessary header include * docs: add utility process net module limitations * test: run net module tests in utility process individually * refactor: clean up prior utility process net tests * chore: add resolveHost to utility process net module * chore: replace resolve host dcheck with sequence checker * test: add net module tests for net.resolveHost * docs: remove utility process limitation for resolveHost --------- Co-authored-by: deepak1556 <hop2deep@gmail.com> Co-authored-by: Cheng Zhao <github@zcbenz.com>
This commit is contained in:
parent
f229201f41
commit
8c71e2adc9
29 changed files with 2642 additions and 2290 deletions
108
spec/lib/net-helpers.ts
Normal file
108
spec/lib/net-helpers.ts
Normal file
|
@ -0,0 +1,108 @@
|
|||
import { expect } from 'chai';
|
||||
import * as dns from 'node:dns';
|
||||
import * as http from 'node:http';
|
||||
import { Socket } from 'node:net';
|
||||
import { defer, listen } from './spec-helpers';
|
||||
|
||||
// See https://github.com/nodejs/node/issues/40702.
|
||||
dns.setDefaultResultOrder('ipv4first');
|
||||
|
||||
export const kOneKiloByte = 1024;
|
||||
export const kOneMegaByte = kOneKiloByte * kOneKiloByte;
|
||||
|
||||
export function randomBuffer (size: number, start: number = 0, end: number = 255) {
|
||||
const range = 1 + end - start;
|
||||
const buffer = Buffer.allocUnsafe(size);
|
||||
for (let i = 0; i < size; ++i) {
|
||||
buffer[i] = start + Math.floor(Math.random() * range);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
export function randomString (length: number) {
|
||||
const buffer = randomBuffer(length, '0'.charCodeAt(0), 'z'.charCodeAt(0));
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
export async function getResponse (urlRequest: Electron.ClientRequest) {
|
||||
return new Promise<Electron.IncomingMessage>((resolve, reject) => {
|
||||
urlRequest.on('error', reject);
|
||||
urlRequest.on('abort', reject);
|
||||
urlRequest.on('response', (response) => resolve(response));
|
||||
urlRequest.end();
|
||||
});
|
||||
}
|
||||
|
||||
export async function collectStreamBody (response: Electron.IncomingMessage | http.IncomingMessage) {
|
||||
return (await collectStreamBodyBuffer(response)).toString();
|
||||
}
|
||||
|
||||
export function collectStreamBodyBuffer (response: Electron.IncomingMessage | http.IncomingMessage) {
|
||||
return new Promise<Buffer>((resolve, reject) => {
|
||||
response.on('error', reject);
|
||||
(response as NodeJS.EventEmitter).on('aborted', reject);
|
||||
const data: Buffer[] = [];
|
||||
response.on('data', (chunk) => data.push(chunk));
|
||||
response.on('end', (chunk?: Buffer) => {
|
||||
if (chunk) data.push(chunk);
|
||||
resolve(Buffer.concat(data));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function respondNTimes (fn: http.RequestListener, n: number): Promise<string> {
|
||||
const server = http.createServer((request, response) => {
|
||||
fn(request, response);
|
||||
// don't close if a redirect was returned
|
||||
if ((response.statusCode < 300 || response.statusCode >= 399) && n <= 0) {
|
||||
n--;
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
const sockets: Socket[] = [];
|
||||
server.on('connection', s => sockets.push(s));
|
||||
defer(() => {
|
||||
server.close();
|
||||
for (const socket of sockets) {
|
||||
socket.destroy();
|
||||
}
|
||||
});
|
||||
return (await listen(server)).url;
|
||||
}
|
||||
|
||||
export function respondOnce (fn: http.RequestListener) {
|
||||
return respondNTimes(fn, 1);
|
||||
}
|
||||
|
||||
respondNTimes.routeFailure = false;
|
||||
|
||||
respondNTimes.toRoutes = (routes: Record<string, http.RequestListener>, n: number) => {
|
||||
return respondNTimes((request, response) => {
|
||||
if (Object.hasOwn(routes, request.url || '')) {
|
||||
(async () => {
|
||||
await Promise.resolve(routes[request.url || ''](request, response));
|
||||
})().catch((err) => {
|
||||
respondNTimes.routeFailure = true;
|
||||
console.error('Route handler failed, this is probably why your test failed', err);
|
||||
response.statusCode = 500;
|
||||
response.end();
|
||||
});
|
||||
} else {
|
||||
response.statusCode = 500;
|
||||
response.end();
|
||||
expect.fail(`Unexpected URL: ${request.url}`);
|
||||
}
|
||||
}, n);
|
||||
};
|
||||
respondOnce.toRoutes = (routes: Record<string, http.RequestListener>) => respondNTimes.toRoutes(routes, 1);
|
||||
|
||||
respondNTimes.toURL = (url: string, fn: http.RequestListener, n: number) => {
|
||||
return respondNTimes.toRoutes({ [url]: fn }, n);
|
||||
};
|
||||
respondOnce.toURL = (url: string, fn: http.RequestListener) => respondNTimes.toURL(url, fn, 1);
|
||||
|
||||
respondNTimes.toSingleURL = (fn: http.RequestListener, n: number) => {
|
||||
const requestUrl = '/requestUrl';
|
||||
return respondNTimes.toURL(requestUrl, fn, n).then(url => `${url}${requestUrl}`);
|
||||
};
|
||||
respondOnce.toSingleURL = (fn: http.RequestListener) => respondNTimes.toSingleURL(fn, 1);
|
Loading…
Add table
Add a link
Reference in a new issue