Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// service_
"/events"
"/data"
"/other"
"/more"
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import { getTypeFromTypeReference } from "./utils/getTypeFromTypeReference";
import { wrapTypeReferenceAsOptional } from "./utils/wrapTypeReferenceAsOptional";

class HeaderWithCount {
public readonly schema: RawSchemas.HttpHeaderSchema;
public schema: RawSchemas.HttpHeaderSchema;
public count = 0;
private hasIncompatibleSchemas = false;

constructor(schema: RawSchemas.HttpHeaderSchema) {
this.schema = schema;
Expand All @@ -22,6 +23,14 @@ class HeaderWithCount {
public increment(): void {
this.count += 1;
}

public markIncompatible(): void {
this.hasIncompatibleSchemas = true;
}

public isIncompatible(): boolean {
return this.hasIncompatibleSchemas;
}
}

/* 75% of endpoints must have header present, for it to be considered a global header*/
Expand Down Expand Up @@ -101,6 +110,20 @@ export function buildGlobalHeaders(context: OpenApiIrConverterContext): void {
});
headerWithCount = new HeaderWithCount(convertedHeader);
globalHeaders[header.name] = headerWithCount;
} else {
// Check if the current header schema is compatible with the existing one
const currentConvertedHeader = buildHeader({
header,
fileContainingReference: RelativeFilePath.of(ROOT_API_FILENAME),
context,
namespace: undefined
});
const existingType = getTypeFromHttpHeaderSchema(headerWithCount.schema);
const currentType = getTypeFromHttpHeaderSchema(currentConvertedHeader);
if (existingType !== currentType) {
// Schemas are incompatible, widen the type to string
headerWithCount.markIncompatible();
}
}
headerWithCount.increment();
}
Expand All @@ -115,16 +138,37 @@ export function buildGlobalHeaders(context: OpenApiIrConverterContext): void {
if (predefinedHeader != null) {
continue; // already added
} else if (isRequired) {
// If schemas are incompatible, widen the type to string
const schema = header.isIncompatible() ? widenToString(header.schema) : header.schema;
context.builder.addGlobalHeader({
name: headerName,
schema: header.schema
schema
});
} else if (isOptional) {
// If schemas are incompatible, widen the type to string
const schema = header.isIncompatible() ? widenToString(header.schema) : header.schema;
context.builder.addGlobalHeader({
name: headerName,
schema: wrapTypeReferenceAsOptional(header.schema)
schema: wrapTypeReferenceAsOptional(schema)
});
}
}
}
}

function getTypeFromHttpHeaderSchema(schema: RawSchemas.HttpHeaderSchema): string {
if (typeof schema === "string") {
return schema;
}
return schema.type;
}

function widenToString(schema: RawSchemas.HttpHeaderSchema): RawSchemas.HttpHeaderSchema {
if (typeof schema === "string") {
return "string";
}
return {
...schema,
type: "string"
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "object",
"properties": {
"id": {
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"definitions": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "object",
"properties": {
"value": {
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"definitions": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "object",
"properties": {
"name": {
"oneOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"definitions": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
api:
specs:
- openapi: ./openapi.yml
89 changes: 89 additions & 0 deletions test-definitions/fern/apis/openapi-accept-header/openapi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
openapi: 3.0.3
info:
title: Accept Header Test API
version: 1.0.0
description: Test API for Accept header with text/event-stream default
paths:
/events:
get:
operationId: getEvents
summary: Get events stream
description: Returns a stream of events
parameters:
- $ref: '#/components/parameters/AcceptEventStream'
responses:
'200':
description: Successful response
content:
text/event-stream:
schema:
type: string
/data:
get:
operationId: getData
summary: Get data as JSON
description: Returns data as JSON
parameters:
- $ref: '#/components/parameters/AcceptJson'
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
id:
type: string
/other:
get:
operationId: getOther
summary: Get other data as JSON
description: Returns other data as JSON
parameters:
- $ref: '#/components/parameters/AcceptJson'
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
name:
type: string
/more:
get:
operationId: getMore
summary: Get more data as JSON
description: Returns more data as JSON
parameters:
- $ref: '#/components/parameters/AcceptJson'
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
value:
type: string
components:
parameters:
AcceptEventStream:
name: Accept
in: header
required: true
description: The MIME type of the response body.
schema:
type: string
default: 'text/event-stream'
AcceptJson:
name: Accept
in: header
required: true
description: The MIME type of the response body.
schema:
type: string
const: 'application/json'
Loading