Skip to content

Commit 286e31e

Browse files
authored
Rewrite Got (sindresorhus#1051)
1 parent c6efc24 commit 286e31e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+3500
-2636
lines changed

benchmark/index.ts

+200
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
'use strict';
2+
import {URL} from 'url';
3+
import https = require('https');
4+
import axios from 'axios';
5+
import Benchmark = require('benchmark');
6+
import fetch from 'node-fetch';
7+
import request = require('request');
8+
import got from '../source';
9+
import PromisableRequest from '../source/as-promise/core';
10+
import Request, {kIsNormalizedAlready} from '../source/core';
11+
12+
const {normalizeArguments} = PromisableRequest;
13+
14+
// Configuration
15+
const httpsAgent = new https.Agent({
16+
keepAlive: true,
17+
rejectUnauthorized: false
18+
});
19+
20+
const url = new URL('https://127.0.0.1:8080');
21+
const urlString = url.toString();
22+
23+
const gotOptions = {
24+
agent: {
25+
https: httpsAgent
26+
},
27+
rejectUnauthorized: false,
28+
retry: 0
29+
};
30+
31+
const normalizedGotOptions = normalizeArguments(url, gotOptions);
32+
normalizedGotOptions[kIsNormalizedAlready] = true;
33+
34+
const requestOptions = {
35+
strictSSL: false,
36+
agent: httpsAgent
37+
};
38+
39+
const fetchOptions = {
40+
agent: httpsAgent
41+
};
42+
43+
const axiosOptions = {
44+
url: urlString,
45+
httpsAgent,
46+
rejectUnauthorized: false
47+
};
48+
49+
const axiosStreamOptions: typeof axiosOptions & {responseType: 'stream'} = {
50+
...axiosOptions,
51+
responseType: 'stream'
52+
};
53+
54+
const httpsOptions = {
55+
rejectUnauthorized: false,
56+
agent: httpsAgent
57+
};
58+
59+
const suite = new Benchmark.Suite();
60+
61+
// Benchmarking
62+
suite.add('got - promise', {
63+
defer: true,
64+
fn: async (deferred: {resolve(): void}) => {
65+
await got(url, gotOptions);
66+
deferred.resolve();
67+
}
68+
}).add('got - stream', {
69+
defer: true,
70+
fn: async (deferred: {resolve(): void}) => {
71+
got.stream(url, gotOptions).resume().once('end', () => {
72+
deferred.resolve();
73+
});
74+
}
75+
}).add('got - promise core', {
76+
defer: true,
77+
fn: async (deferred: {resolve(): void}) => {
78+
const stream = new PromisableRequest(url, gotOptions);
79+
stream.resume().once('end', () => {
80+
deferred.resolve();
81+
});
82+
}
83+
}).add('got - stream core', {
84+
defer: true,
85+
fn: async (deferred: {resolve(): void}) => {
86+
const stream = new Request(url, gotOptions);
87+
stream.resume().once('end', () => {
88+
deferred.resolve();
89+
});
90+
}
91+
}).add('got - stream core - normalized options', {
92+
defer: true,
93+
fn: async (deferred: {resolve(): void}) => {
94+
const stream = new Request(undefined as any, normalizedGotOptions);
95+
stream.resume().once('end', () => {
96+
deferred.resolve();
97+
});
98+
}
99+
}).add('request - callback', {
100+
defer: true,
101+
fn: (deferred: {resolve(): void}) => {
102+
request(urlString, requestOptions, (error: Error) => {
103+
if (error) {
104+
throw error;
105+
}
106+
107+
deferred.resolve();
108+
});
109+
}
110+
}).add('request - stream', {
111+
defer: true,
112+
fn: (deferred: {resolve(): void}) => {
113+
const stream = request(urlString, requestOptions);
114+
stream.resume();
115+
stream.once('end', () => {
116+
deferred.resolve();
117+
});
118+
}
119+
}).add('node-fetch - promise', {
120+
defer: true,
121+
fn: async (deferred: {resolve(): void}) => {
122+
const response = await fetch(url, fetchOptions);
123+
await response.text();
124+
125+
deferred.resolve();
126+
}
127+
}).add('node-fetch - stream', {
128+
defer: true,
129+
fn: async (deferred: {resolve(): void}) => {
130+
const {body} = await fetch(url, fetchOptions);
131+
132+
body.resume();
133+
body.once('end', () => {
134+
deferred.resolve();
135+
});
136+
}
137+
}).add('axios - promise', {
138+
defer: true,
139+
fn: async (deferred: {resolve(): void}) => {
140+
await axios.request(axiosOptions);
141+
deferred.resolve();
142+
}
143+
}).add('axios - stream', {
144+
defer: true,
145+
fn: async (deferred: {resolve(): void}) => {
146+
const {data} = await axios.request(axiosStreamOptions);
147+
data.resume();
148+
data.once('end', () => {
149+
deferred.resolve();
150+
});
151+
}
152+
}).add('https - stream', {
153+
defer: true,
154+
fn: (deferred: {resolve(): void}) => {
155+
https.request(urlString, httpsOptions, response => {
156+
response.resume();
157+
response.once('end', () => {
158+
deferred.resolve();
159+
});
160+
}).end();
161+
}
162+
}).on('cycle', (event: Benchmark.Event) => {
163+
console.log(String(event.target));
164+
}).on('complete', function (this: any) {
165+
console.log(`Fastest is ${this.filter('fastest').map('name') as string}`);
166+
167+
internalBenchmark();
168+
}).run();
169+
170+
const internalBenchmark = (): void => {
171+
console.log();
172+
173+
const internalSuite = new Benchmark.Suite();
174+
internalSuite.add('got - normalize options', {
175+
fn: () => {
176+
normalizeArguments(url, gotOptions);
177+
}
178+
}).on('cycle', (event: Benchmark.Event) => {
179+
console.log(String(event.target));
180+
});
181+
182+
internalSuite.run();
183+
};
184+
185+
// Results (i7-7700k, CPU governor: performance):
186+
// got - promise x 3,092 ops/sec ±5.25% (73 runs sampled)
187+
// got - stream x 4,313 ops/sec ±5.61% (72 runs sampled)
188+
// got - promise core x 6,756 ops/sec ±5.32% (80 runs sampled)
189+
// got - stream core x 6,863 ops/sec ±4.68% (76 runs sampled)
190+
// got - stream core - normalized options x 7,960 ops/sec ±3.83% (81 runs sampled)
191+
// request - callback x 6,912 ops/sec ±6.50% (76 runs sampled)
192+
// request - stream x 7,821 ops/sec ±4.28% (80 runs sampled)
193+
// node-fetch - promise x 7,036 ops/sec ±8.17% (78 runs sampled)
194+
// node-fetch - stream x 7,877 ops/sec ±4.17% (80 runs sampled)
195+
// axios - promise x 6,613 ops/sec ±3.22% (76 runs sampled)
196+
// axios - stream x 8,642 ops/sec ±2.84% (79 runs sampled)
197+
// https - stream x 9,955 ops/sec ±6.36% (76 runs sampled)
198+
// Fastest is https - stream
199+
200+
// got - normalize options x 166,389 ops/sec ±0.63% (91 runs sampled)

benchmark/server.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {AddressInfo} from 'net';
2+
import https = require('https');
3+
// @ts-ignore No types
4+
import createCert = require('create-cert');
5+
6+
(async () => {
7+
const keys = await createCert({days: 365, commonName: 'localhost'});
8+
9+
const server = https.createServer(keys, (_request, response) => {
10+
response.end('ok');
11+
}).listen(8080, () => {
12+
const {port} = server.address() as AddressInfo;
13+
14+
console.log(`Listening at https://localhost:${port}`);
15+
});
16+
})();

package.json

+20-23
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
"funding": "https://github.com/sindresorhus/got?sponsor=1",
88
"main": "dist/source",
99
"engines": {
10-
"node": ">=10"
10+
"node": ">=10.19.0"
1111
},
1212
"scripts": {
13-
"test": "xo && tsc --noEmit && nyc ava",
13+
"test": "xo && tsc --noEmit && nyc --reporter=html --reporter=text ava",
1414
"release": "np",
1515
"build": "del-cli dist && tsc",
1616
"prepare": "npm run build"
@@ -33,71 +33,68 @@
3333
"fetch",
3434
"net",
3535
"network",
36-
"electron",
36+
"gzip",
3737
"brotli",
3838
"requests",
3939
"human-friendly",
4040
"axios",
41-
"superagent"
41+
"superagent",
42+
"node-fetch",
43+
"ky"
4244
],
4345
"dependencies": {
44-
"@sindresorhus/is": "^2.0.0",
46+
"@sindresorhus/is": "^2.1.0",
4547
"@szmarczak/http-timer": "^4.0.0",
4648
"@types/cacheable-request": "^6.0.1",
47-
"@types/keyv": "3.1.1",
48-
"@types/responselike": "1.0.0",
49-
"cacheable-lookup": "^2.0.0",
49+
"@types/responselike": "^1.0.0",
50+
"cacheable-lookup": "^4.1.1",
5051
"cacheable-request": "^7.0.1",
5152
"decompress-response": "^5.0.0",
52-
"duplexer3": "^0.1.4",
5353
"get-stream": "^5.0.0",
54+
"http2-wrapper": "^1.0.0-beta.4.3",
5455
"lowercase-keys": "^2.0.0",
55-
"mimic-response": "^2.1.0",
5656
"p-cancelable": "^2.0.0",
57-
"p-event": "^4.0.0",
58-
"responselike": "^2.0.0",
59-
"to-readable-stream": "^2.0.0",
60-
"type-fest": "^0.10.0"
57+
"responselike": "^2.0.0"
6158
},
6259
"devDependencies": {
6360
"@ava/typescript": "^1.1.1",
6461
"@sindresorhus/tsconfig": "^0.7.0",
65-
"@types/duplexer3": "^0.1.0",
62+
"@types/benchmark": "^1.0.31",
6663
"@types/express": "^4.17.2",
6764
"@types/lolex": "^5.1.0",
6865
"@types/node": "13.1.2",
69-
"@types/proxyquire": "^1.3.28",
66+
"@types/node-fetch": "^2.5.5",
67+
"@types/request": "^2.48.4",
7068
"@types/sinon": "^7.0.13",
7169
"@types/tough-cookie": "^2.3.5",
7270
"@typescript-eslint/eslint-plugin": "^2.19.2",
7371
"@typescript-eslint/parser": "^2.19.2",
7472
"ava": "^3.3.0",
73+
"axios": "^0.19.2",
74+
"benchmark": "^2.1.4",
7575
"coveralls": "^3.0.4",
7676
"create-test-server": "^3.0.1",
7777
"del-cli": "^3.0.0",
7878
"delay": "^4.3.0",
7979
"eslint-config-xo-typescript": "^0.26.0",
8080
"express": "^4.17.1",
8181
"form-data": "^3.0.0",
82-
"get-port": "^5.0.0",
83-
"keyv": "^4.0.0",
8482
"lolex": "^6.0.0",
8583
"nock": "^12.0.0",
84+
"node-fetch": "^2.6.0",
8685
"np": "^6.0.0",
8786
"nyc": "^15.0.0",
88-
"proxyquire": "^2.0.1",
87+
"p-event": "^4.0.0",
8988
"sinon": "^8.1.1",
9089
"slow-stream": "0.0.4",
9190
"tempy": "^0.4.0",
91+
"to-readable-stream": "^2.1.0",
9292
"tough-cookie": "^3.0.0",
9393
"typescript": "3.7.5",
94-
"xo": "^0.26.0"
94+
"xo": "^0.26.1"
9595
},
9696
"types": "dist/source",
9797
"sideEffects": false,
98-
"browser": {
99-
"electron": false
100-
},
10198
"ava": {
10299
"files": [
103100
"test/*"

0 commit comments

Comments
 (0)