Skip to content

Commit bac5169

Browse files
committed
Fix cookie parameters silently dropped in API calls
The schema declared `in: cookie` as valid but callApi never sent them. Cookie parameters are now collected and sent as a Cookie header.
1 parent 61624e5 commit bac5169

2 files changed

Lines changed: 34 additions & 0 deletions

File tree

src/api/call.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,33 @@ describe('callApi', () => {
330330
expect(options.body).toBe(JSON.stringify({ amount: '1000' }));
331331
});
332332

333+
test('sends cookie parameters as Cookie header', async () => {
334+
const api = makeApi();
335+
const endpoint = makeEndpoint({
336+
parameters: [
337+
{ name: 'session', in: 'cookie', required: true, secret: false, fixed: 'abc123' },
338+
{ name: 'tracking', in: 'cookie', required: false, secret: false },
339+
],
340+
});
341+
342+
await callApi(api, endpoint, { tracking: 'xyz' });
343+
344+
const { options } = fetchCallArguments();
345+
expect((options.headers as Record<string, string>)['Cookie']).toBe('session=abc123; tracking=xyz');
346+
});
347+
348+
test('omits Cookie header when no cookie parameters have values', async () => {
349+
const api = makeApi();
350+
const endpoint = makeEndpoint({
351+
parameters: [{ name: 'session', in: 'cookie', required: false, secret: false }],
352+
});
353+
354+
await callApi(api, endpoint, {});
355+
356+
const { options } = fetchCallArguments();
357+
expect((options.headers as Record<string, string>)['Cookie']).toBeUndefined();
358+
});
359+
333360
test('returns null data for empty response body (204 No Content)', async () => {
334361
fetchMock.mockResolvedValue({
335362
text: () => Promise.resolve(''),

src/api/call.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ async function callApi(
4343
const headerParameters = Object.fromEntries(
4444
resolvedParameters.filter((p) => p.in === 'header' && !isNil(p.value)).map((p) => [p.name, p.value as string])
4545
);
46+
const cookieParameters = resolvedParameters.filter((p) => p.in === 'cookie' && !isNil(p.value));
4647
const bodyParameters = Object.fromEntries(
4748
resolvedParameters.filter((p) => p.in === 'body' && !isNil(p.value)).map((p) => [p.name, p.value])
4849
);
@@ -65,6 +66,12 @@ async function callApi(
6566
...api.headers,
6667
};
6768

69+
if (cookieParameters.length > 0) {
70+
const cookieString = cookieParameters.map((p) => `${p.name}=${p.value as string}`).join('; ');
71+
const existing = headers['Cookie'];
72+
headers['Cookie'] = existing ? `${existing}; ${cookieString}` : cookieString; // eslint-disable-line functional/immutable-data
73+
}
74+
6875
const hasBody = endpoint.method === 'POST' || endpoint.method === 'PUT' || endpoint.method === 'PATCH';
6976
const body = hasBody && Object.keys(bodyParameters).length > 0 ? JSON.stringify(bodyParameters) : undefined;
7077

0 commit comments

Comments
 (0)