1
+ import type { OutgoingHttpHeaders } from 'node:http' ;
1
2
import https , { type RequestOptions } from 'node:https' ;
2
3
3
4
/**
@@ -20,6 +21,32 @@ const httpRequest = (params: RequestOptions): Promise<unknown> =>
20
21
params . timeout = 5000 ;
21
22
}
22
23
24
+ // Ensure some common headers are present. Many sites (including AWS docs)
25
+ // block requests that don't include a User-Agent or typical Accept header,
26
+ // which is why the `fetch` call (which sets defaults) succeeds while a
27
+ // bare https.request may receive a 403.
28
+ const originalHeaders = ( params . headers ?? { } ) as OutgoingHttpHeaders ;
29
+ // Create a quick lowercase map of header names to detect presence case-insensitively
30
+ const lowerMap = Object . keys ( originalHeaders ) . reduce <
31
+ Record < string , string >
32
+ > ( ( acc , k ) => {
33
+ acc [ k . toLowerCase ( ) ] = k ;
34
+ return acc ;
35
+ } , { } ) ;
36
+
37
+ // Only add defaults when not present (case-insensitive)
38
+ if ( ! lowerMap [ 'user-agent' ] ) {
39
+ // prefer a Node/undici-like UA to match what fetch/undici would send
40
+ ( originalHeaders as Record < string , string > ) [ 'User-Agent' ] =
41
+ 'node-fetch/1.0 (+https://github.com/node-fetch/node-fetch)' ;
42
+ }
43
+ if ( ! lowerMap . accept ) {
44
+ ( originalHeaders as Record < string , string > ) . Accept =
45
+ 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' ;
46
+ }
47
+
48
+ params . headers = originalHeaders ;
49
+
23
50
const req = https . request ( params , ( res ) => {
24
51
if (
25
52
res . statusCode == null ||
0 commit comments