Skip to content

Commit 05aa48b

Browse files
committed
TRAC-525: fix - client.ts not using Header object for default values
1 parent a792a86 commit 05aa48b

2 files changed

Lines changed: 33 additions & 12 deletions

File tree

.changeset/fresh-steaks-remain.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@bigcommerce/catalyst-client": patch
3+
---
4+
5+
Fix `client.fetch` so that custom headers passed via `fetchOptions.headers` properly override the client's default headers (including `Authorization`). Previously the merge produced two distinct keys (e.g. `Authorization` and `authorization`) in a plain object, which `fetch` then `append`ed into a comma-joined value. Headers are now built via a `Headers` object using `.set()`, so case-insensitive overrides work as expected.

packages/client/src/client.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -130,20 +130,36 @@ class Client<FetcherRequestInit extends RequestInit = RequestInit> {
130130
const { headers: additionalFetchHeaders = {}, ...additionalFetchOptions } =
131131
(await this.beforeRequest?.(fetchOptions)) ?? {};
132132

133+
// Build headers via a Headers object so that case-insensitive overrides work as expected.
134+
const requestHeaders = new Headers({
135+
'Content-Type': 'application/json',
136+
Authorization: `Bearer ${this.config.storefrontToken}`,
137+
'User-Agent': this.backendUserAgent,
138+
});
139+
140+
if (customerAccessToken) {
141+
requestHeaders.set('X-Bc-Customer-Access-Token', customerAccessToken);
142+
}
143+
144+
if (validateCustomerAccessToken) {
145+
requestHeaders.set('X-Bc-Error-On-Invalid-Customer-Access-Token', 'true');
146+
}
147+
148+
if (this.trustedProxySecret) {
149+
requestHeaders.set('X-BC-Trusted-Proxy-Secret', this.trustedProxySecret);
150+
}
151+
152+
new Headers(additionalFetchHeaders).forEach((value, key) => {
153+
requestHeaders.set(key, value);
154+
});
155+
156+
new Headers(headers).forEach((value, key) => {
157+
requestHeaders.set(key, value);
158+
});
159+
133160
const response = await fetch(graphqlUrl, {
134161
method: 'POST',
135-
headers: {
136-
'Content-Type': 'application/json',
137-
Authorization: `Bearer ${this.config.storefrontToken}`,
138-
'User-Agent': this.backendUserAgent,
139-
...(customerAccessToken && { 'X-Bc-Customer-Access-Token': customerAccessToken }),
140-
...(validateCustomerAccessToken && {
141-
'X-Bc-Error-On-Invalid-Customer-Access-Token': 'true',
142-
}),
143-
...(this.trustedProxySecret && { 'X-BC-Trusted-Proxy-Secret': this.trustedProxySecret }),
144-
...Object.fromEntries(new Headers(additionalFetchHeaders).entries()),
145-
...Object.fromEntries(new Headers(headers).entries()),
146-
},
162+
headers: requestHeaders,
147163
body: JSON.stringify({
148164
query,
149165
...(variables && { variables }),

0 commit comments

Comments
 (0)