Require Node.js 22 · sindresorhus/got@b933476 (original) (raw)
``
1
`+
import process from 'node:process';
`
``
2
`+
import crypto from 'node:crypto';
`
1
3
`import got from '../../dist/source/index.js';
`
2
4
``
``
5
`+
// Signing requests
`
``
6
+
3
7
`/*
`
4
``
`-
- Got supports composing multiple instances together. This is very powerful.
`
5
``
`-
`
6
``
`-
- You can create a client that limits download/upload size,
`
7
``
`-
- then compose it with an instance that signs a request.
`
8
``
`-
`
9
``
`-
- It's like plugins without any of the plugin mess.
`
10
``
`-
- You just create instances and then compose them together.
`
11
``
`-
`
12
``
`` -
- To mix them use
instanceA.extend(instanceB, instanceC, ...), that's all.
``
13
``
`-
- Let's begin.
`
``
8
`+
Got supports composing multiple instances together. This is very powerful.
`
``
9
+
``
10
`+
You can create a client that limits download/upload size, then compose it with an instance that signs a request.
`
``
11
+
``
12
`+
It's like plugins without any of the plugin mess.
`
``
13
`+
You just create instances and then compose them together.
`
``
14
+
``
15
`` +
To mix them use instanceA.extend(instanceB, instanceC, ...), that's all.
``
``
16
+
``
17
`+
Let's begin.
`
14
18
`*/
`
15
19
``
16
20
`` // Logging all got(…) calls
``
`@@ -19,8 +23,8 @@ const logger = got.extend({
`
19
23
`(options, next) => {
`
20
24
`` console.log(Sending <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>o</mi><mi>p</mi><mi>t</mi><mi>i</mi><mi>o</mi><mi>n</mi><mi>s</mi><mi mathvariant="normal">.</mi><mi>m</mi><mi>e</mi><mi>t</mi><mi>h</mi><mi>o</mi><mi>d</mi></mrow><mi>t</mi><mi>o</mi></mrow><annotation encoding="application/x-tex">{options.method} to </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">o</span><span class="mord mathnormal">pt</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal">m</span><span class="mord mathnormal">e</span><span class="mord mathnormal">t</span><span class="mord mathnormal">h</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span></span><span class="mord mathnormal">t</span><span class="mord mathnormal">o</span></span></span></span>{options.url});
``
21
25
`return next(options);
`
22
``
`-
}
`
23
``
`-
]
`
``
26
`+
},
`
``
27
`+
],
`
24
28
`});
`
25
29
``
26
30
`// Denying redirects to foreign hosts
`
`@@ -32,9 +36,9 @@ const controlRedirects = got.extend({
`
32
36
`if (options.url.origin !== origin) {
`
33
37
`` throw new Error(Redirection to <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>o</mi><mi>p</mi><mi>t</mi><mi>i</mi><mi>o</mi><mi>n</mi><mi>s</mi><mi mathvariant="normal">.</mi><mi>u</mi><mi>r</mi><mi>l</mi><mi mathvariant="normal">.</mi><mi>o</mi><mi>r</mi><mi>i</mi><mi>g</mi><mi>i</mi><mi>n</mi></mrow><mi>i</mi><mi>s</mi><mi>n</mi><mi>o</mi><mi>t</mi><mi>a</mi><mi>l</mi><mi>l</mi><mi>o</mi><mi>w</mi><mi>e</mi><mi>d</mi><mi>f</mi><mi>r</mi><mi>o</mi><mi>m</mi></mrow><annotation encoding="application/x-tex">{options.url.origin} is not allowed from </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">o</span><span class="mord mathnormal">pt</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.02778em;">or</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">in</span></span><span class="mord mathnormal">i</span><span class="mord mathnormal">s</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mord mathnormal">t</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal">o</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.10764em;">df</span><span class="mord mathnormal">ro</span><span class="mord mathnormal">m</span></span></span></span>{origin});
``
34
38
`}
`
35
``
`-
}
`
36
``
`-
]
`
37
``
`-
}
`
``
39
`+
},
`
``
40
`+
],
`
``
41
`+
},
`
38
42
`});
`
39
43
``
40
44
`// Limiting download & upload size
`
`@@ -46,7 +50,7 @@ const limitDownloadUpload = got.extend({
`
46
50
``
47
51
`// Create an AbortController if limits are set and signal not already provided
`
48
52
`let controller;
`
49
``
`-
let signal = options.signal;
`
``
53
`+
let {signal} = options;
`
50
54
``
51
55
`if ((downloadLimit || uploadLimit) && !signal) {
`
52
56
`controller = new AbortController();
`
`@@ -85,25 +89,22 @@ const limitDownloadUpload = got.extend({
`
85
89
`}
`
86
90
``
87
91
`return promiseOrStream;
`
88
``
`-
}
`
89
``
`-
]
`
``
92
`+
},
`
``
93
`+
],
`
90
94
`});
`
91
95
``
92
96
`// No user agent
`
93
97
`const noUserAgent = got.extend({
`
94
98
`headers: {
`
95
``
`-
'user-agent': undefined
`
96
``
`-
}
`
``
99
`+
'user-agent': undefined,
`
``
100
`+
},
`
97
101
`});
`
98
102
``
99
103
`// Custom endpoint
`
100
104
`const httpbin = got.extend({
`
101
``
`-
prefixUrl: 'https://httpbin.org/'
`
``
105
`+
prefixUrl: 'https://httpbin.org/',
`
102
106
`});
`
103
107
``
104
``
`-
// Signing requests
`
105
``
`-
import crypto from 'node:crypto';
`
106
``
-
107
108
`const getMessageSignature = (data, secret) => crypto.createHmac('sha256', secret).update(data).digest('hex').toUpperCase();
`
108
109
`const signRequest = got.extend({
`
109
110
`hooks: {
`
`@@ -112,11 +113,11 @@ const signRequest = got.extend({
`
112
113
`const secret = options.context.secret ?? process.env.SECRET;
`
113
114
``
114
115
`if (secret) {
`
115
``
`-
options.headers['sign'] = getMessageSignature(options.body ?? '', secret);
`
``
116
`+
options.headers.sign = getMessageSignature(options.body ?? '', secret);
`
116
117
`}
`
117
``
`-
}
`
118
``
`-
]
`
119
``
`-
}
`
``
118
`+
},
`
``
119
`+
],
`
``
120
`+
},
`
120
121
`});
`
121
122
``
122
123
`/*
`
`@@ -128,15 +129,15 @@ const merged = got.extend(
`
128
129
`limitDownloadUpload,
`
129
130
`httpbin,
`
130
131
`signRequest,
`
131
``
`-
controlRedirects
`
``
132
`+
controlRedirects,
`
132
133
`);
`
133
134
``
134
135
`// There's no 'user-agent' header :)
`
135
136
`const {headers} = await merged.post('anything', {
`
136
137
`body: 'foobar',
`
137
138
`context: {
`
138
``
`-
secret: 'password'
`
139
``
`-
}
`
``
139
`+
secret: 'password',
`
``
140
`+
},
`
140
141
`}).json();
`
141
142
``
142
143
`console.log(headers);
`
`@@ -149,13 +150,13 @@ console.log(headers);
`
149
150
`// Sign: 'EB0167A1EBF205510BAFF5DA1465537944225F0E0140E1880B746F361FF11DCA'
`
150
151
`// }
`
151
152
``
152
``
`-
const MEGABYTE = 1048576;
`
``
153
`+
const MEGABYTE = 1_048_576;
`
153
154
`try {
`
154
155
`await merged('https://pop-iso.sfo2.cdn.digitaloceanspaces.com/21.04/amd64/intel/5/pop-os_21.04_amd64_intel_5.iso', {
`
155
156
`context: {
`
156
``
`-
downloadLimit: MEGABYTE
`
``
157
`+
downloadLimit: MEGABYTE,
`
157
158
`},
`
158
``
`-
prefixUrl: ''
`
``
159
`+
prefixUrl: '',
`
159
160
`});
`
160
161
`} catch (error) {
`
161
162
`// AbortError: This operation was aborted.
`