1+ import type { OutgoingHttpHeaders } from 'node:http' ;
12import https , { type RequestOptions } from 'node:https' ;
23
34/**
@@ -20,6 +21,32 @@ const httpRequest = (params: RequestOptions): Promise<unknown> =>
2021 params . timeout = 5000 ;
2122 }
2223
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+
2350 const req = https . request ( params , ( res ) => {
2451 if (
2552 res . statusCode == null ||
0 commit comments