Skip to content

Commit 5638fa6

Browse files
authored
[Feat][DEVX-793] Allow Passing Custom Headers to Http Requests (#1291)
* feat(sdk-client-v3): pass custom headers to requests - pass custom headers to request headers * feat(sdk-client-v3): pass custom headers to requests - pass custom headers to request headers - add tests to validate functionality * Allow passing custom headers to HTTP requests Add support for custom headers in HTTP requests. * feat(sdk-client-v3): pass custom headers to requests - pass custom headers to request headers - add tests to validate functionality
1 parent b56a502 commit 5638fa6

4 files changed

Lines changed: 136 additions & 1 deletion

File tree

.changeset/neat-wings-bow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@commercetools/ts-client": patch
3+
---
4+
5+
[Feat][DEVX-793] Allow Passing Custom Headers to Http Requests

packages/sdk-client-v3/src/types/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ export type IClientOptions = {
305305
retryConfig?: RetryOptions
306306
maskSensitiveHeaderData?: boolean
307307
httpClientOptions?: object
308+
request?: MiddlewareRequest
308309
}
309310

310311
export type HttpClientOptions = IClientOptions & Optional

packages/sdk-client-v3/src/utils/executor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export default async function executor(request: HttpClientConfig) {
5757
...options,
5858
...rest,
5959
headers: {
60-
...rest.headers,
60+
...Object.assign({}, rest.headers, rest.request?.headers ?? {}),
6161
},
6262

6363
// for axios
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import executor from '../../src/utils/executor'
2+
import { HttpClientConfig } from '../../src/types/types'
3+
4+
const mockResponse = {
5+
data: { ok: true },
6+
status: 200,
7+
statusCode: 200,
8+
headers: {},
9+
}
10+
11+
function createExecutorConfig(
12+
overrides: Partial<HttpClientConfig> & {
13+
httpClient?: jest.Mock
14+
} = {}
15+
): HttpClientConfig {
16+
const httpClient =
17+
overrides.httpClient ?? jest.fn(() => Promise.resolve(mockResponse))
18+
19+
return {
20+
url: 'https://api.example.com/test',
21+
method: 'GET',
22+
headers: {},
23+
request: {
24+
uri: '/test',
25+
method: 'GET',
26+
body: null,
27+
headers: {},
28+
},
29+
httpClient,
30+
...overrides,
31+
}
32+
}
33+
34+
describe('executor', () => {
35+
describe('request headers', () => {
36+
test('passes rest.headers to httpClient', async () => {
37+
const httpClient = jest.fn(() => Promise.resolve(mockResponse))
38+
39+
await executor(
40+
createExecutorConfig({
41+
httpClient,
42+
headers: { 'X-Client-Header': 'client-value' },
43+
})
44+
)
45+
46+
expect(httpClient).toHaveBeenCalledWith(
47+
'https://api.example.com/test',
48+
expect.objectContaining({
49+
headers: { 'X-Client-Header': 'client-value' },
50+
})
51+
)
52+
})
53+
54+
test('merges rest.request.headers with rest.headers', async () => {
55+
const httpClient = jest.fn(() => Promise.resolve(mockResponse))
56+
57+
await executor(
58+
createExecutorConfig({
59+
httpClient,
60+
headers: { 'X-Client-Header': 'client-value' },
61+
request: {
62+
uri: '/test',
63+
method: 'GET',
64+
body: null,
65+
headers: { 'X-Request-Header': 'request-value' },
66+
},
67+
})
68+
)
69+
70+
expect(httpClient).toHaveBeenCalledWith(
71+
'https://api.example.com/test',
72+
expect.objectContaining({
73+
headers: {
74+
'X-Client-Header': 'client-value',
75+
'X-Request-Header': 'request-value',
76+
},
77+
})
78+
)
79+
})
80+
81+
test('rest.request.headers override rest.headers on conflict', async () => {
82+
const httpClient = jest.fn(() => Promise.resolve(mockResponse))
83+
84+
await executor(
85+
createExecutorConfig({
86+
httpClient,
87+
headers: { 'X-Shared-Header': 'client-value' },
88+
request: {
89+
uri: '/test',
90+
method: 'GET',
91+
body: null,
92+
headers: { 'X-Shared-Header': 'request-value' },
93+
},
94+
})
95+
)
96+
97+
expect(httpClient).toHaveBeenCalledWith(
98+
'https://api.example.com/test',
99+
expect.objectContaining({
100+
headers: { 'X-Shared-Header': 'request-value' },
101+
})
102+
)
103+
})
104+
105+
test('uses only rest.headers when rest.request.headers is undefined', async () => {
106+
const httpClient = jest.fn(() => Promise.resolve(mockResponse))
107+
108+
await executor(
109+
createExecutorConfig({
110+
httpClient,
111+
headers: { Authorization: 'Bearer token' },
112+
request: {
113+
uri: '/test',
114+
method: 'GET',
115+
body: null,
116+
headers: undefined as unknown as Record<string, string>,
117+
},
118+
})
119+
)
120+
121+
expect(httpClient).toHaveBeenCalledWith(
122+
'https://api.example.com/test',
123+
expect.objectContaining({
124+
headers: { Authorization: 'Bearer token' },
125+
})
126+
)
127+
})
128+
})
129+
})

0 commit comments

Comments
 (0)