Support Nodejs.24 - Merge pull request #2110 from actions/salmanmkc/node24

Support Node.js 24
This commit is contained in:
Salman Chishti authored and GitHub committed 2025-10-16 16:25:47 +01:00
commit 56a0b54831
9 files changed
+235 -291

No files matched your search

+2 -2
View File
@@ -7,7 +7,7 @@ A lightweight HTTP client optimized for building actions.
- HTTP client with TypeScript generics and async/await/Promises
- Typings included!
- [Proxy support](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-self-hosted-runners#using-a-proxy-server-with-self-hosted-runners) just works with actions and the runner
- Targets ES2019 (runner runs actions with node 12+). Only supported on node 12+.
- Targets ES2019 (runner runs actions with node 24+). Only supported on node 20+.
- Basic, Bearer and PAT Support out of the box. Extensible handlers for others.
- Redirects supported
@@ -44,7 +44,7 @@ export NODE_DEBUG=http
## Node support
The http-client is built using the latest LTS version of Node 12. It may work on previous node LTS versions but it's tested and officially supported on Node12+.
The http-client is built using Node 24. It may work on previous node LTS versions but it's tested and officially supported on Node 20+.
## Support and Versioning
+6 -6
View File
@@ -15,7 +15,7 @@ describe('auth', () => {
bh
])
const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
@@ -26,7 +26,7 @@ describe('auth', () => {
'base64'
).toString()
expect(creds).toBe('johndoe:password')
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
it('does basic http get request with pat token auth', async () => {
@@ -38,7 +38,7 @@ describe('auth', () => {
ph
])
const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
@@ -49,7 +49,7 @@ describe('auth', () => {
'base64'
).toString()
expect(creds).toBe(`PAT:${token}`)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
it('does basic http get request with pat token auth', async () => {
@@ -60,13 +60,13 @@ describe('auth', () => {
ph
])
const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
const auth: string = obj.headers.authorization
expect(auth).toBe(`Bearer ${token}`)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
})
+46 -46
View File
@@ -37,41 +37,41 @@ describe('basics', () => {
// "user-agent": "typed-test-client-tests"
// },
// "origin": "173.95.152.44",
// "url": "http://postman-echo.com/get"
// "url": "https://postman-echo.com/get"
// }
it('does basic http get request', async () => {
const res: httpm.HttpClientResponse = await _http.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
expect(obj.headers['user-agent']).toBeTruthy()
})
it('does basic http get request with no user agent', async () => {
const http: httpm.HttpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
expect(obj.headers['user-agent']).toBeFalsy()
})
/* TODO write a mock rather then relying on a third party
it('does basic https get request', async () => {
const res: httpm.HttpClientResponse = await _http.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
*/
it('does basic http get request with default headers', async () => {
@@ -86,14 +86,14 @@ describe('basics', () => {
}
)
const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.headers.accept).toBe('application/json')
expect(obj.headers['content-type']).toBe('application/json')
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
it('does basic http get request with merged headers', async () => {
@@ -108,7 +108,7 @@ describe('basics', () => {
}
)
const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get',
'https://postman-echo.com/get',
{
'content-type': 'application/x-www-form-urlencoded'
}
@@ -120,18 +120,18 @@ describe('basics', () => {
expect(obj.headers['content-type']).toBe(
'application/x-www-form-urlencoded'
)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
it('pipes a get request', async () => {
return new Promise<void>(async resolve => {
const file = fs.createWriteStream(sampleFilePath)
;(await _http.get('http://postman-echo.com/get')).message
;(await _http.get('https://postman-echo.com/get')).message
.pipe(file)
.on('close', () => {
const body: string = fs.readFileSync(sampleFilePath).toString()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
resolve()
})
})
@@ -139,32 +139,32 @@ describe('basics', () => {
it('does basic get request with redirects', async () => {
const res: httpm.HttpClientResponse = await _http.get(
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
'http://postman-echo.com/get'
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
'https://postman-echo.com/get'
)}`
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
it('does basic get request with redirects (303)', async () => {
const res: httpm.HttpClientResponse = await _http.get(
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
'http://postman-echo.com/get'
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
'https://postman-echo.com/get'
)}&status_code=303`
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
it('returns 404 for not found get request on redirect', async () => {
const res: httpm.HttpClientResponse = await _http.get(
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
'http://postman-echo.com/status/404'
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
'https://postman-echo.com/status/404'
)}&status_code=303`
)
expect(res.message.statusCode).toBe(404)
@@ -178,8 +178,8 @@ describe('basics', () => {
{allowRedirects: false}
)
const res: httpm.HttpClientResponse = await http.get(
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
'http://postman-echo.com/get'
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
'https://postman-echo.com/get'
)}`
)
expect(res.message.statusCode).toBe(302)
@@ -192,8 +192,8 @@ describe('basics', () => {
authorization: 'shhh'
}
const res: httpm.HttpClientResponse = await _http.get(
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
'http://www.postman-echo.com/get'
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
'https://www.postman-echo.com/get'
)}`,
headers
)
@@ -205,7 +205,7 @@ describe('basics', () => {
expect(obj.headers[httpm.Headers.Accept]).toBe('application/json')
expect(obj.headers['Authorization']).toBeUndefined()
expect(obj.headers['authorization']).toBeUndefined()
expect(obj.url).toBe('http://www.postman-echo.com/get')
expect(obj.url).toBe('https://www.postman-echo.com/get')
})
it('does not pass Auth with diff hostname redirects', async () => {
@@ -214,8 +214,8 @@ describe('basics', () => {
Authorization: 'shhh'
}
const res: httpm.HttpClientResponse = await _http.get(
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
'http://www.postman-echo.com/get'
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
'https://www.postman-echo.com/get'
)}`,
headers
)
@@ -227,19 +227,19 @@ describe('basics', () => {
expect(obj.headers[httpm.Headers.Accept]).toBe('application/json')
expect(obj.headers['Authorization']).toBeUndefined()
expect(obj.headers['authorization']).toBeUndefined()
expect(obj.url).toBe('http://www.postman-echo.com/get')
expect(obj.url).toBe('https://www.postman-echo.com/get')
})
it('does basic head request', async () => {
const res: httpm.HttpClientResponse = await _http.head(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
})
it('does basic http delete request', async () => {
const res: httpm.HttpClientResponse = await _http.del(
'http://postman-echo.com/delete'
'https://postman-echo.com/delete'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
@@ -249,32 +249,32 @@ describe('basics', () => {
it('does basic http post request', async () => {
const b = 'Hello World!'
const res: httpm.HttpClientResponse = await _http.post(
'http://postman-echo.com/post',
'https://postman-echo.com/post',
b
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.data).toBe(b)
expect(obj.url).toBe('http://postman-echo.com/post')
expect(obj.url).toBe('https://postman-echo.com/post')
})
it('does basic http patch request', async () => {
const b = 'Hello World!'
const res: httpm.HttpClientResponse = await _http.patch(
'http://postman-echo.com/patch',
'https://postman-echo.com/patch',
b
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.data).toBe(b)
expect(obj.url).toBe('http://postman-echo.com/patch')
expect(obj.url).toBe('https://postman-echo.com/patch')
})
it('does basic http options request', async () => {
const res: httpm.HttpClientResponse = await _http.options(
'http://postman-echo.com'
'https://postman-echo.com'
)
expect(res.message.statusCode).toBe(200)
await res.readBody()
@@ -282,7 +282,7 @@ describe('basics', () => {
it('returns 404 for not found get request', async () => {
const res: httpm.HttpClientResponse = await _http.get(
'http://postman-echo.com/status/404'
'https://postman-echo.com/status/404'
)
expect(res.message.statusCode).toBe(404)
await res.readBody()
@@ -290,11 +290,11 @@ describe('basics', () => {
it('gets a json object', async () => {
const jsonObj = await _http.getJson<HttpBinData>(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(jsonObj.statusCode).toBe(200)
expect(jsonObj.result).toBeDefined()
expect(jsonObj.result?.url).toBe('http://postman-echo.com/get')
expect(jsonObj.result?.url).toBe('https://postman-echo.com/get')
expect(jsonObj.result?.headers[httpm.Headers.Accept]).toBe(
httpm.MediaTypes.ApplicationJson
)
@@ -305,7 +305,7 @@ describe('basics', () => {
it('getting a non existent json object returns null', async () => {
const jsonObj = await _http.getJson<HttpBinData>(
'http://postman-echo.com/status/404'
'https://postman-echo.com/status/404'
)
expect(jsonObj.statusCode).toBe(404)
expect(jsonObj.result).toBeNull()
@@ -314,12 +314,12 @@ describe('basics', () => {
it('posts a json object', async () => {
const res = {name: 'foo'}
const restRes = await _http.postJson<HttpBinData>(
'http://postman-echo.com/post',
'https://postman-echo.com/post',
res
)
expect(restRes.statusCode).toBe(200)
expect(restRes.result).toBeDefined()
expect(restRes.result?.url).toBe('http://postman-echo.com/post')
expect(restRes.result?.url).toBe('https://postman-echo.com/post')
expect(restRes.result?.json.name).toBe('foo')
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe(
httpm.MediaTypes.ApplicationJson
@@ -335,12 +335,12 @@ describe('basics', () => {
it('puts a json object', async () => {
const res = {name: 'foo'}
const restRes = await _http.putJson<HttpBinData>(
'http://postman-echo.com/put',
'https://postman-echo.com/put',
res
)
expect(restRes.statusCode).toBe(200)
expect(restRes.result).toBeDefined()
expect(restRes.result?.url).toBe('http://postman-echo.com/put')
expect(restRes.result?.url).toBe('https://postman-echo.com/put')
expect(restRes.result?.json.name).toBe('foo')
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe(
@@ -357,12 +357,12 @@ describe('basics', () => {
it('patch a json object', async () => {
const res = {name: 'foo'}
const restRes = await _http.patchJson<HttpBinData>(
'http://postman-echo.com/patch',
'https://postman-echo.com/patch',
res
)
expect(restRes.statusCode).toBe(200)
expect(restRes.result).toBeDefined()
expect(restRes.result?.url).toBe('http://postman-echo.com/patch')
expect(restRes.result?.url).toBe('https://postman-echo.com/patch')
expect(restRes.result?.json.name).toBe('foo')
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe(
httpm.MediaTypes.ApplicationJson
+8 -8
View File
@@ -12,7 +12,7 @@ describe('headers', () => {
it('preserves existing headers on getJson', async () => {
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
let jsonObj = await _http.getJson<any>(
'http://postman-echo.com/get',
'https://postman-echo.com/get',
additionalHeaders
)
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('foo')
@@ -26,7 +26,7 @@ describe('headers', () => {
[httpm.Headers.Accept]: 'baz'
}
}
jsonObj = await httpWithHeaders.getJson<any>('http://postman-echo.com/get')
jsonObj = await httpWithHeaders.getJson<any>('https://postman-echo.com/get')
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain(
httpm.MediaTypes.ApplicationJson
@@ -36,7 +36,7 @@ describe('headers', () => {
it('preserves existing headers on postJson', async () => {
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
let jsonObj = await _http.postJson<any>(
'http://postman-echo.com/post',
'https://postman-echo.com/post',
{},
additionalHeaders
)
@@ -52,7 +52,7 @@ describe('headers', () => {
}
}
jsonObj = await httpWithHeaders.postJson<any>(
'http://postman-echo.com/post',
'https://postman-echo.com/post',
{}
)
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
@@ -64,7 +64,7 @@ describe('headers', () => {
it('preserves existing headers on putJson', async () => {
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
let jsonObj = await _http.putJson<any>(
'http://postman-echo.com/put',
'https://postman-echo.com/put',
{},
additionalHeaders
)
@@ -80,7 +80,7 @@ describe('headers', () => {
}
}
jsonObj = await httpWithHeaders.putJson<any>(
'http://postman-echo.com/put',
'https://postman-echo.com/put',
{}
)
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
@@ -92,7 +92,7 @@ describe('headers', () => {
it('preserves existing headers on patchJson', async () => {
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
let jsonObj = await _http.patchJson<any>(
'http://postman-echo.com/patch',
'https://postman-echo.com/patch',
{},
additionalHeaders
)
@@ -108,7 +108,7 @@ describe('headers', () => {
}
}
jsonObj = await httpWithHeaders.patchJson<any>(
'http://postman-echo.com/patch',
'https://postman-echo.com/patch',
{}
)
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
+10 -10
View File
@@ -13,30 +13,30 @@ describe('basics', () => {
it.each([true, false])('creates Agent with keepAlive %s', keepAlive => {
const http = new httpm.HttpClient('http-client-tests', [], {keepAlive})
const agent = http.getAgent('http://postman-echo.com')
const agent = http.getAgent('https://postman-echo.com')
expect(agent).toHaveProperty('keepAlive', keepAlive)
})
it('does basic http get request with keepAlive true', async () => {
const res: httpm.HttpClientResponse = await _http.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
})
it('does basic head request with keepAlive true', async () => {
const res: httpm.HttpClientResponse = await _http.head(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
})
it('does basic http delete request with keepAlive true', async () => {
const res: httpm.HttpClientResponse = await _http.del(
'http://postman-echo.com/delete'
'https://postman-echo.com/delete'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
@@ -46,32 +46,32 @@ describe('basics', () => {
it('does basic http post request with keepAlive true', async () => {
const b = 'Hello World!'
const res: httpm.HttpClientResponse = await _http.post(
'http://postman-echo.com/post',
'https://postman-echo.com/post',
b
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.data).toBe(b)
expect(obj.url).toBe('http://postman-echo.com/post')
expect(obj.url).toBe('https://postman-echo.com/post')
})
it('does basic http patch request with keepAlive true', async () => {
const b = 'Hello World!'
const res: httpm.HttpClientResponse = await _http.patch(
'http://postman-echo.com/patch',
'https://postman-echo.com/patch',
b
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.data).toBe(b)
expect(obj.url).toBe('http://postman-echo.com/patch')
expect(obj.url).toBe('https://postman-echo.com/patch')
})
it('does basic http options request with keepAlive true', async () => {
const res: httpm.HttpClientResponse = await _http.options(
'http://postman-echo.com'
'https://postman-echo.com'
)
expect(res.message.statusCode).toBe(200)
await res.readBody()
+10 -10
View File
@@ -196,16 +196,16 @@ describe('proxy', () => {
})
it('HttpClient does basic http get request through proxy', async () => {
process.env['http_proxy'] = _proxyUrl
process.env['https_proxy'] = _proxyUrl
const httpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await httpClient.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(_proxyConnects).toEqual(['postman-echo.com:80'])
expect(obj.url).toBe('https://postman-echo.com/get')
expect(_proxyConnects).toEqual(['postman-echo.com:443'])
})
it('HttpClient does basic http get request when bypass proxy', async () => {
@@ -213,12 +213,12 @@ describe('proxy', () => {
process.env['no_proxy'] = 'postman-echo.com'
const httpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await httpClient.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
expect(_proxyConnects).toHaveLength(0)
})
@@ -228,12 +228,12 @@ describe('proxy', () => {
process.env['https_proxy'] = _proxyUrl
const httpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await httpClient.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
expect(_proxyConnects).toEqual(['postman-echo.com:443'])
})
*/
@@ -243,12 +243,12 @@ describe('proxy', () => {
process.env['no_proxy'] = 'postman-echo.com'
const httpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await httpClient.get(
'http://postman-echo.com/get'
'https://postman-echo.com/get'
)
expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody()
const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get')
expect(obj.url).toBe('https://postman-echo.com/get')
expect(_proxyConnects).toHaveLength(0)
})
+59 -189
View File
@@ -1,43 +1,49 @@
{
"name": "@actions/http-client",
"version": "2.2.3",
"lockfileVersion": 2,
"version": "3.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@actions/http-client",
"version": "2.2.3",
"version": "3.0.0",
"license": "MIT",
"dependencies": {
"tunnel": "^0.0.6",
"undici": "^5.28.5"
},
"devDependencies": {
"@types/node": "20.7.1",
"@types/node": "24.1.0",
"@types/proxy": "^1.0.1",
"@types/tunnel": "0.0.3",
"proxy": "^2.1.1"
}
},
"node_modules/@fastify/busboy": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/@types/node": {
"version": "20.7.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz",
"integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==",
"dev": true
"version": "24.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz",
"integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.8.0"
}
},
"node_modules/@types/proxy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/proxy/-/proxy-1.0.2.tgz",
"integrity": "sha512-NDNsg7YuClVzEenn9SUButu43blypWvljGsIkDV7HI4N9apjrS0aeeMTUG0PYa71lD1AvIgvjkBagqHDiomDjA==",
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@types/proxy/-/proxy-1.0.4.tgz",
"integrity": "sha512-KnYy7hpp3wXQ2U0ExvCMF9BvWZ6h2aI0XWb8g705mn26Zmn2HO/eLRi6UuhHELA6MNJtYtiZYWv38gobJN0xXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
@@ -47,6 +53,7 @@
"resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.3.tgz",
"integrity": "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
@@ -56,6 +63,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^1.9.0"
},
@@ -68,6 +76,7 @@
"resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz",
"integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==",
"dev": true,
"license": "MIT",
"dependencies": {
"camelcase": "5.0.0",
"chalk": "2.4.2",
@@ -89,6 +98,7 @@
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
@@ -98,6 +108,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
@@ -112,6 +123,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "1.1.3"
}
@@ -120,15 +132,17 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.1.2"
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
@@ -144,6 +158,7 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.0"
}
@@ -153,6 +168,7 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
@@ -162,6 +178,7 @@
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -171,26 +188,32 @@
"resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
"integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT"
},
"node_modules/proxy": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.1.1.tgz",
"integrity": "sha512-nLgd7zdUAOpB3ZO/xCkU8gy74UER7P0aihU8DkUsDS5ZoFwVCX7u8dy+cv5tVK8UaB/yminU1GiLWE26TKPYpg==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.2.0.tgz",
"integrity": "sha512-nYclNIWj9UpXbVJ3W5EXIYiGR88AKZoGt90kyh3zoOBY5QW+7bbtPvMFgKGD4VJmpS3UXQXtlGXSg3lRNLOFLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"args": "^5.0.3",
"basic-auth-parser": "0.0.2-1",
"debug": "^4.3.4"
},
"bin": {
"proxy": "dist/bin/proxy.js"
},
"engines": {
"node": ">= 14"
}
@@ -200,6 +223,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^3.0.0"
},
@@ -211,14 +235,15 @@
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"license": "MIT",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/undici": {
"version": "5.28.5",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
"version": "5.29.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
"license": "MIT",
"dependencies": {
"@fastify/busboy": "^2.0.0"
@@ -226,168 +251,13 @@
"engines": {
"node": ">=14.0"
}
}
},
"dependencies": {
"@fastify/busboy": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ=="
},
"@types/node": {
"version": "20.7.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz",
"integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==",
"dev": true
},
"@types/proxy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/proxy/-/proxy-1.0.2.tgz",
"integrity": "sha512-NDNsg7YuClVzEenn9SUButu43blypWvljGsIkDV7HI4N9apjrS0aeeMTUG0PYa71lD1AvIgvjkBagqHDiomDjA==",
"node_modules/undici-types": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/tunnel": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.3.tgz",
"integrity": "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"args": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz",
"integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==",
"dev": true,
"requires": {
"camelcase": "5.0.0",
"chalk": "2.4.2",
"leven": "2.1.0",
"mri": "1.1.4"
}
},
"basic-auth-parser": {
"version": "0.0.2-1",
"resolved": "https://registry.npmjs.org/basic-auth-parser/-/basic-auth-parser-0.0.2-1.tgz",
"integrity": "sha512-GFj8iVxo9onSU6BnnQvVwqvxh60UcSHJEDnIk3z4B6iOjsKSmqe+ibW0Rsz7YO7IE1HG3D3tqCNIidP46SZVdQ==",
"dev": true
},
"camelcase": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
"dev": true
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"dev": true
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"requires": {
"ms": "2.1.2"
}
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true
},
"leven": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
"dev": true
},
"mri": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
"integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
"dev": true
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"proxy": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.1.1.tgz",
"integrity": "sha512-nLgd7zdUAOpB3ZO/xCkU8gy74UER7P0aihU8DkUsDS5ZoFwVCX7u8dy+cv5tVK8UaB/yminU1GiLWE26TKPYpg==",
"dev": true,
"requires": {
"args": "^5.0.3",
"basic-auth-parser": "0.0.2-1",
"debug": "^4.3.4"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"undici": {
"version": "5.28.5",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
"requires": {
"@fastify/busboy": "^2.0.0"
}
"license": "MIT"
}
}
}
+5 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@actions/http-client",
"version": "2.2.3",
"version": "3.0.0",
"description": "Actions Http Client",
"keywords": [
"github",
@@ -39,7 +39,7 @@
"url": "https://github.com/actions/toolkit/issues"
},
"devDependencies": {
"@types/node": "20.7.1",
"@types/node": "24.1.0",
"@types/tunnel": "0.0.3",
"proxy": "^2.1.1",
"@types/proxy": "^1.0.1"
@@ -47,5 +47,8 @@
"dependencies": {
"tunnel": "^0.0.6",
"undici": "^5.28.5"
},
"overrides": {
"uri-js": "npm:uri-js-replace@^1.0.1"
}
}
+89 -18
View File
@@ -275,11 +275,11 @@ export class HttpClient {
Headers.Accept,
MediaTypes.ApplicationJson
)
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(
additionalHeaders,
Headers.ContentType,
MediaTypes.ApplicationJson
)
additionalHeaders[Headers.ContentType] =
this._getExistingOrDefaultContentTypeHeader(
additionalHeaders,
MediaTypes.ApplicationJson
)
const res: HttpClientResponse = await this.post(
requestUrl,
data,
@@ -299,11 +299,11 @@ export class HttpClient {
Headers.Accept,
MediaTypes.ApplicationJson
)
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(
additionalHeaders,
Headers.ContentType,
MediaTypes.ApplicationJson
)
additionalHeaders[Headers.ContentType] =
this._getExistingOrDefaultContentTypeHeader(
additionalHeaders,
MediaTypes.ApplicationJson
)
const res: HttpClientResponse = await this.put(
requestUrl,
data,
@@ -323,11 +323,11 @@ export class HttpClient {
Headers.Accept,
MediaTypes.ApplicationJson
)
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(
additionalHeaders,
Headers.ContentType,
MediaTypes.ApplicationJson
)
additionalHeaders[Headers.ContentType] =
this._getExistingOrDefaultContentTypeHeader(
additionalHeaders,
MediaTypes.ApplicationJson
)
const res: HttpClientResponse = await this.patch(
requestUrl,
data,
@@ -628,16 +628,87 @@ export class HttpClient {
return lowercaseKeys(headers || {})
}
/**
* Gets an existing header value or returns a default.
* Handles converting number header values to strings since HTTP headers must be strings.
* Note: This returns string | string[] since some headers can have multiple values.
* For headers that must always be a single string (like Content-Type), use the
* specialized _getExistingOrDefaultContentTypeHeader method instead.
*/
private _getExistingOrDefaultHeader(
additionalHeaders: http.OutgoingHttpHeaders,
header: string,
_default: string
): string | number | string[] {
): string | string[] {
let clientHeader: string | string[] | undefined
if (this.requestOptions && this.requestOptions.headers) {
const headerValue = lowercaseKeys(this.requestOptions.headers)[header]
if (headerValue) {
clientHeader =
typeof headerValue === 'number' ? headerValue.toString() : headerValue
}
}
const additionalValue = additionalHeaders[header]
if (additionalValue !== undefined) {
return typeof additionalValue === 'number'
? additionalValue.toString()
: additionalValue
}
if (clientHeader !== undefined) {
return clientHeader
}
return _default
}
/**
* Specialized version of _getExistingOrDefaultHeader for Content-Type header.
* Always returns a single string (not an array) since Content-Type should be a single value.
* Converts arrays to comma-separated strings and numbers to strings to ensure type safety.
* This was split from _getExistingOrDefaultHeader to provide stricter typing for callers
* that assign the result to places expecting a string (e.g., additionalHeaders[Headers.ContentType]).
*/
private _getExistingOrDefaultContentTypeHeader(
additionalHeaders: http.OutgoingHttpHeaders,
_default: string
): string {
let clientHeader: string | undefined
if (this.requestOptions && this.requestOptions.headers) {
clientHeader = lowercaseKeys(this.requestOptions.headers)[header]
const headerValue = lowercaseKeys(this.requestOptions.headers)[
Headers.ContentType
]
if (headerValue) {
if (typeof headerValue === 'number') {
clientHeader = String(headerValue)
} else if (Array.isArray(headerValue)) {
clientHeader = headerValue.join(', ')
} else {
clientHeader = headerValue
}
}
}
return additionalHeaders[header] || clientHeader || _default
const additionalValue = additionalHeaders[Headers.ContentType]
// Return the first non-undefined value, converting numbers or arrays to strings if necessary
if (additionalValue !== undefined) {
if (typeof additionalValue === 'number') {
return String(additionalValue)
} else if (Array.isArray(additionalValue)) {
return additionalValue.join(', ')
} else {
return additionalValue
}
}
if (clientHeader !== undefined) {
return clientHeader
}
return _default
}
private _getAgent(parsedUrl: URL): http.Agent {