feat: [net] add "priority" option to net.request (#42628)
document the default value of priority option Update the priority test to not use the httpbin.org as server Fixed the lint errors Fixed the build error
This commit is contained in:
parent
cf6c662702
commit
dc5efca0f6
5 changed files with 103 additions and 2 deletions
|
@ -60,6 +60,10 @@ following properties:
|
|||
`strict-origin-when-cross-origin`.
|
||||
* `cache` string (optional) - can be `default`, `no-store`, `reload`,
|
||||
`no-cache`, `force-cache` or `only-if-cached`.
|
||||
* `priority` string (optional) - can be `throttled`, `idle`, `lowest`,
|
||||
`low`, `medium`, or `highest`. Defaults to `idle`.
|
||||
* `priorityIncremental` boolean (optional) - the incremental loading flag as part
|
||||
of HTTP extensible priorities (RFC 9218). Default is `true`.
|
||||
|
||||
`options` properties such as `protocol`, `host`, `hostname`, `port` and `path`
|
||||
strictly follow the Node.js model as described in the
|
||||
|
|
|
@ -288,8 +288,12 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod
|
|||
origin: options.origin,
|
||||
referrerPolicy: options.referrerPolicy,
|
||||
cache: options.cache,
|
||||
allowNonHttpProtocols: Object.hasOwn(options, kAllowNonHttpProtocols)
|
||||
allowNonHttpProtocols: Object.hasOwn(options, kAllowNonHttpProtocols),
|
||||
priority: options.priority
|
||||
};
|
||||
if ('priorityIncremental' in options) {
|
||||
urlLoaderOptions.priorityIncremental = options.priorityIncremental;
|
||||
}
|
||||
const headers: Record<string, string | string[]> = options.headers || {};
|
||||
for (const [name, value] of Object.entries(headers)) {
|
||||
validateHeader(name, value);
|
||||
|
|
|
@ -638,6 +638,24 @@ gin::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
|
|||
break;
|
||||
}
|
||||
|
||||
if (std::string priority; opts.Get("priority", &priority)) {
|
||||
static constexpr auto Lookup =
|
||||
base::MakeFixedFlatMap<std::string_view, net::RequestPriority>({
|
||||
{"throttled", net::THROTTLED},
|
||||
{"idle", net::IDLE},
|
||||
{"lowest", net::LOWEST},
|
||||
{"low", net::LOW},
|
||||
{"medium", net::MEDIUM},
|
||||
{"highest", net::HIGHEST},
|
||||
});
|
||||
if (auto iter = Lookup.find(priority); iter != Lookup.end())
|
||||
request->priority = iter->second;
|
||||
}
|
||||
if (bool priorityIncremental = request->priority_incremental;
|
||||
opts.Get("priorityIncremental", &priorityIncremental)) {
|
||||
request->priority_incremental = priorityIncremental;
|
||||
}
|
||||
|
||||
const bool use_session_cookies =
|
||||
opts.ValueOrDefault("useSessionCookies", false);
|
||||
int options = network::mojom::kURLLoadOptionSniffMimeType;
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
import { net, ClientRequest, ClientRequestConstructorOptions, utilityProcess } from 'electron/main';
|
||||
import { net, session, ClientRequest, ClientRequestConstructorOptions, utilityProcess } from 'electron/main';
|
||||
|
||||
import { expect } from 'chai';
|
||||
|
||||
import { once } from 'node:events';
|
||||
import * as fs from 'node:fs';
|
||||
import * as http from 'node:http';
|
||||
import * as http2 from 'node:http2';
|
||||
import * as path from 'node:path';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
|
||||
import { collectStreamBody, collectStreamBodyBuffer, getResponse, kOneKiloByte, kOneMegaByte, randomBuffer, randomString, respondNTimes, respondOnce } from './lib/net-helpers';
|
||||
import { listen, defer } from './lib/spec-helpers';
|
||||
|
||||
const utilityFixturePath = path.resolve(__dirname, 'fixtures', 'api', 'utility-process', 'api-net-spec.js');
|
||||
const fixturesPath = path.resolve(__dirname, 'fixtures');
|
||||
|
||||
async function itUtility (name: string, fn?: Function, args?: {[key:string]: any}) {
|
||||
it(`${name} in utility process`, async () => {
|
||||
|
@ -46,6 +50,34 @@ describe('net module', () => {
|
|||
}
|
||||
});
|
||||
|
||||
let http2URL: string;
|
||||
|
||||
const certPath = path.join(fixturesPath, 'certificates');
|
||||
const h2server = http2.createSecureServer({
|
||||
key: fs.readFileSync(path.join(certPath, 'server.key')),
|
||||
cert: fs.readFileSync(path.join(certPath, 'server.pem'))
|
||||
}, async (req, res) => {
|
||||
if (req.method === 'POST') {
|
||||
const chunks = [];
|
||||
for await (const chunk of req) chunks.push(chunk);
|
||||
res.end(Buffer.concat(chunks).toString('utf8'));
|
||||
} else if (req.method === 'GET' && req.headers[':path'] === '/get') {
|
||||
res.end(JSON.stringify({
|
||||
headers: req.headers
|
||||
}));
|
||||
} else {
|
||||
res.end('<html></html>');
|
||||
}
|
||||
});
|
||||
|
||||
before(async () => {
|
||||
http2URL = (await listen(h2server)).url + '/';
|
||||
});
|
||||
|
||||
after(() => {
|
||||
h2server.close();
|
||||
});
|
||||
|
||||
for (const test of [itIgnoringArgs, itUtility]) {
|
||||
describe('HTTP basics', () => {
|
||||
test('should be able to issue a basic GET request', async () => {
|
||||
|
@ -1615,4 +1647,45 @@ describe('net module', () => {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (const test of [itIgnoringArgs]) {
|
||||
describe('ClientRequest API', () => {
|
||||
for (const [priorityName, urgency] of Object.entries({
|
||||
throttled: 'u=5',
|
||||
idle: 'u=4',
|
||||
lowest: '',
|
||||
low: 'u=2',
|
||||
medium: 'u=1',
|
||||
highest: 'u=0'
|
||||
})) {
|
||||
for (const priorityIncremental of [true, false]) {
|
||||
test(`should set priority to ${priorityName}/${priorityIncremental} if requested`, async () => {
|
||||
// Priority header is available on HTTP/2, which is only
|
||||
// supported over TLS, so...
|
||||
session.defaultSession.setCertificateVerifyProc((req, cb) => cb(0));
|
||||
defer(() => {
|
||||
session.defaultSession.setCertificateVerifyProc(null);
|
||||
});
|
||||
|
||||
const urlRequest = net.request({
|
||||
url: `${http2URL}get`,
|
||||
priority: priorityName as any,
|
||||
priorityIncremental
|
||||
});
|
||||
const response = await getResponse(urlRequest);
|
||||
const data = JSON.parse(await collectStreamBody(response));
|
||||
let expectedPriority = urgency;
|
||||
if (priorityIncremental) {
|
||||
expectedPriority = expectedPriority ? expectedPriority + ', i' : 'i';
|
||||
}
|
||||
if (expectedPriority === '') {
|
||||
expect(data.headers.priority).to.be.undefined();
|
||||
} else {
|
||||
expect(data.headers.priority).to.be.a('string').and.equal(expectedPriority);
|
||||
}
|
||||
}, { priorityName, urgency, priorityIncremental });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
2
typings/internal-ambient.d.ts
vendored
2
typings/internal-ambient.d.ts
vendored
|
@ -177,6 +177,8 @@ declare namespace NodeJS {
|
|||
mode?: string;
|
||||
destination?: string;
|
||||
bypassCustomProtocolHandlers?: boolean;
|
||||
priority?: 'throttled' | 'idle' | 'lowest' | 'low' | 'medium' | 'highest';
|
||||
priorityIncremental?: boolean;
|
||||
};
|
||||
type ResponseHead = {
|
||||
statusCode: number;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue