Skip to content

Commit eedefdd

Browse files
authored
Handle optional security headers (#3128)
1 parent f5e152d commit eedefdd

File tree

4 files changed

+44
-13
lines changed

4 files changed

+44
-13
lines changed

.changeset/stupid-hats-reflect.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@gitbook/react-openapi': patch
3+
---
4+
5+
Handle optional security headers

packages/react-openapi/src/OpenAPISecurities.tsx

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import type { OpenAPIV3_1 } from '@gitbook/openapi-parser';
21
import { InteractiveSection } from './InteractiveSection';
32
import { Markdown } from './Markdown';
43
import { OpenAPISchemaName } from './OpenAPISchemaName';
5-
import type { OpenAPIClientContext, OpenAPIOperationData } from './types';
4+
import type {
5+
OpenAPIClientContext,
6+
OpenAPIOperationData,
7+
OpenAPISecurityWithRequired,
8+
} from './types';
69
import { resolveDescription } from './utils';
710

811
/**
@@ -50,26 +53,36 @@ export function OpenAPISecurities(props: {
5053
);
5154
}
5255

53-
function getLabelForType(security: OpenAPIV3_1.SecuritySchemeObject) {
56+
function getLabelForType(security: OpenAPISecurityWithRequired) {
5457
switch (security.type) {
5558
case 'apiKey':
5659
return (
5760
<OpenAPISchemaName
5861
propertyName={security.name ?? 'apiKey'}
5962
type="string"
60-
required
63+
required={security.required}
6164
/>
6265
);
6366
case 'http':
6467
if (security.scheme === 'basic') {
65-
return <OpenAPISchemaName propertyName="Authorization" type="string" required />;
68+
return (
69+
<OpenAPISchemaName
70+
propertyName="Authorization"
71+
type="string"
72+
required={security.required}
73+
/>
74+
);
6675
}
6776

6877
if (security.scheme === 'bearer') {
6978
const description = resolveDescription(security);
7079
return (
7180
<>
72-
<OpenAPISchemaName propertyName="Authorization" type="string" required />
81+
<OpenAPISchemaName
82+
propertyName="Authorization"
83+
type="string"
84+
required={security.required}
85+
/>
7386
{/** Show a default description if none is provided */}
7487
{!description ? (
7588
<Markdown
@@ -81,11 +94,11 @@ function getLabelForType(security: OpenAPIV3_1.SecuritySchemeObject) {
8194
);
8295
}
8396

84-
return <OpenAPISchemaName propertyName="HTTP" required />;
97+
return <OpenAPISchemaName propertyName="HTTP" required={security.required} />;
8598
case 'oauth2':
86-
return <OpenAPISchemaName propertyName="OAuth2" required />;
99+
return <OpenAPISchemaName propertyName="OAuth2" required={security.required} />;
87100
case 'openIdConnect':
88-
return <OpenAPISchemaName propertyName="OpenID Connect" required />;
101+
return <OpenAPISchemaName propertyName="OpenID Connect" required={security.required} />;
89102
default:
90103
// @ts-ignore
91104
return security.type;

packages/react-openapi/src/resolveOpenAPIOperation.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,27 @@ export async function resolveOpenAPIOperation(
4040
}
4141

4242
const servers = 'servers' in schema ? (schema.servers ?? []) : [];
43-
const security = flattenSecurities(operation.security ?? schema.security ?? []);
43+
const security: OpenAPIV3_1.SecurityRequirementObject[] =
44+
operation.security ?? schema.security ?? [];
45+
46+
// If security includes an empty object, it means that the security is optional
47+
const isOptionalSecurity = security.some((entry) => Object.keys(entry).length === 0);
48+
const flatSecurities = flattenSecurities(security);
4449

4550
// Resolve securities
4651
const securities: OpenAPIOperationData['securities'] = [];
47-
for (const entry of security) {
52+
for (const entry of flatSecurities) {
4853
const securityKey = Object.keys(entry)[0];
4954
if (securityKey) {
5055
const securityScheme = schema.components?.securitySchemes?.[securityKey];
5156
if (securityScheme && !checkIsReference(securityScheme)) {
52-
securities.push([securityKey, securityScheme]);
57+
securities.push([
58+
securityKey,
59+
{
60+
...securityScheme,
61+
required: !isOptionalSecurity,
62+
},
63+
]);
5364
}
5465
}
5566
}

packages/react-openapi/src/types.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ export interface OpenAPIContext extends OpenAPIClientContext {
5757
specUrl: string;
5858
}
5959

60+
export type OpenAPISecurityWithRequired = OpenAPIV3.SecuritySchemeObject & { required?: boolean };
61+
6062
export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
6163
path: string;
6264
method: string;
@@ -68,5 +70,5 @@ export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
6870
operation: OpenAPIV3.OperationObject<OpenAPICustomOperationProperties>;
6971

7072
/** Securities that should be used for this operation */
71-
securities: [string, OpenAPIV3.SecuritySchemeObject][];
73+
securities: [string, OpenAPISecurityWithRequired][];
7274
}

0 commit comments

Comments
 (0)