Skip to content

Commit

Permalink
Merge pull request #998 from BitGo/deduplicate-headers
Browse files Browse the repository at this point in the history
fix: deduplicate header parameters
  • Loading branch information
ericcrosson-bitgo authored Jan 28, 2025
2 parents 18321bd + 4d1de4b commit 486df33
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 17 deletions.
39 changes: 22 additions & 17 deletions packages/openapi-generator/src/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,25 +157,30 @@ function parseRequestUnion(
});
}
if (headerSchema.schemas.length > 0) {
// For headers in unions, take properties from first schema that has headers
// Also not perfect but we cannot use the `explode: true` trick for headers
const firstHeaderSchema = schema.schemas.find(
(s) => s.type === 'object' && s.properties['headers']?.type === 'object',
);
if (
firstHeaderSchema?.type === 'object' &&
firstHeaderSchema.properties['headers']?.type === 'object'
) {
const headers = firstHeaderSchema.properties['headers'];
for (const [name, prop] of Object.entries(headers.properties)) {
parameters.push({
type: 'header',
name,
schema: prop,
required: headers.required.includes(name),
});
// For headers in unions, deduplicate and merge properties from all schemas
const headerParams = new Map<string, Parameter>();

for (const subSchema of schema.schemas) {
if (
subSchema.type === 'object' &&
subSchema.properties['headers']?.type === 'object'
) {
const headers = subSchema.properties['headers'];
for (const [name, prop] of Object.entries(headers.properties)) {
// Only add if not already present
if (!headerParams.has(name)) {
headerParams.set(name, {
type: 'header',
name,
schema: prop,
required: headers.required.includes(name),
});
}
}
}
}

parameters.push(...headerParams.values());
}

const firstSubSchema = schema.schemas[0];
Expand Down
61 changes: 61 additions & 0 deletions packages/openapi-generator/test/openapi/union.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,67 @@ testCase("route with unknown unions", ROUTE_WITH_UNKNOWN_UNIONS, {
},
});

const ROUTE_WITH_DUPLICATE_HEADERS = `
import * as t from 'io-ts';
import * as h from '@api-ts/io-ts-http';
export const route = h.httpRoute({
path: '/foo',
method: 'GET',
request: t.union([
h.httpRequest({
headers: {
'x-foo': t.string,
'x-common': t.string,
},
}),
h.httpRequest({
headers: {
'x-bar': t.number,
'x-common': t.string,
},
}),
]),
response: {
200: t.string,
},
});
`;

testCase("route with duplicate headers in request union", ROUTE_WITH_DUPLICATE_HEADERS, {
info: {
title: 'Test',
version: '1.0.0'
},
openapi: '3.0.3',
paths: {
'/foo': {
get: {
parameters: [
{ in: 'header', name: 'x-foo', required: true, schema: { type: 'string' } },
{ in: 'header', name: 'x-common', required: true, schema: { type: 'string' } },
{ in: 'header', name: 'x-bar', required: true, schema: { type: 'number' } },
],
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: {
type: 'string'
}
}
}
}
}
}
}
},
components: {
schemas: {}
}
});

const ROUTE_WITH_REQUEST_UNION = `
import * as t from 'io-ts';
import * as h from '@api-ts/io-ts-http';
Expand Down

0 comments on commit 486df33

Please sign in to comment.