Handle optional security headers (#3128)

This commit is contained in:
Nolann B.
2025-04-09 15:07:33 +02:00
committed by GitHub
parent f5e152dd74
commit eedefdd5c9
4 changed files with 44 additions and 13 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@gitbook/react-openapi': patch
---
Handle optional security headers
@@ -1,8 +1,11 @@
import type { OpenAPIV3_1 } from '@gitbook/openapi-parser';
import { InteractiveSection } from './InteractiveSection';
import { Markdown } from './Markdown';
import { OpenAPISchemaName } from './OpenAPISchemaName';
import type { OpenAPIClientContext, OpenAPIOperationData } from './types';
import type {
OpenAPIClientContext,
OpenAPIOperationData,
OpenAPISecurityWithRequired,
} from './types';
import { resolveDescription } from './utils';
/**
@@ -50,26 +53,36 @@ export function OpenAPISecurities(props: {
);
}
function getLabelForType(security: OpenAPIV3_1.SecuritySchemeObject) {
function getLabelForType(security: OpenAPISecurityWithRequired) {
switch (security.type) {
case 'apiKey':
return (
<OpenAPISchemaName
propertyName={security.name ?? 'apiKey'}
type="string"
required
required={security.required}
/>
);
case 'http':
if (security.scheme === 'basic') {
return <OpenAPISchemaName propertyName="Authorization" type="string" required />;
return (
<OpenAPISchemaName
propertyName="Authorization"
type="string"
required={security.required}
/>
);
}
if (security.scheme === 'bearer') {
const description = resolveDescription(security);
return (
<>
<OpenAPISchemaName propertyName="Authorization" type="string" required />
<OpenAPISchemaName
propertyName="Authorization"
type="string"
required={security.required}
/>
{/** Show a default description if none is provided */}
{!description ? (
<Markdown
@@ -81,11 +94,11 @@ function getLabelForType(security: OpenAPIV3_1.SecuritySchemeObject) {
);
}
return <OpenAPISchemaName propertyName="HTTP" required />;
return <OpenAPISchemaName propertyName="HTTP" required={security.required} />;
case 'oauth2':
return <OpenAPISchemaName propertyName="OAuth2" required />;
return <OpenAPISchemaName propertyName="OAuth2" required={security.required} />;
case 'openIdConnect':
return <OpenAPISchemaName propertyName="OpenID Connect" required />;
return <OpenAPISchemaName propertyName="OpenID Connect" required={security.required} />;
default:
// @ts-ignore
return security.type;
@@ -40,16 +40,27 @@ export async function resolveOpenAPIOperation(
}
const servers = 'servers' in schema ? (schema.servers ?? []) : [];
const security = flattenSecurities(operation.security ?? schema.security ?? []);
const security: OpenAPIV3_1.SecurityRequirementObject[] =
operation.security ?? schema.security ?? [];
// If security includes an empty object, it means that the security is optional
const isOptionalSecurity = security.some((entry) => Object.keys(entry).length === 0);
const flatSecurities = flattenSecurities(security);
// Resolve securities
const securities: OpenAPIOperationData['securities'] = [];
for (const entry of security) {
for (const entry of flatSecurities) {
const securityKey = Object.keys(entry)[0];
if (securityKey) {
const securityScheme = schema.components?.securitySchemes?.[securityKey];
if (securityScheme && !checkIsReference(securityScheme)) {
securities.push([securityKey, securityScheme]);
securities.push([
securityKey,
{
...securityScheme,
required: !isOptionalSecurity,
},
]);
}
}
}
+3 -1
View File
@@ -57,6 +57,8 @@ export interface OpenAPIContext extends OpenAPIClientContext {
specUrl: string;
}
export type OpenAPISecurityWithRequired = OpenAPIV3.SecuritySchemeObject & { required?: boolean };
export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
path: string;
method: string;
@@ -68,5 +70,5 @@ export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
operation: OpenAPIV3.OperationObject<OpenAPICustomOperationProperties>;
/** Securities that should be used for this operation */
securities: [string, OpenAPIV3.SecuritySchemeObject][];
securities: [string, OpenAPISecurityWithRequired][];
}