mirror of
https://github.com/Redocly/redoc.git
synced 2025-01-31 10:04:08 +03:00
fix: path parameters are not correctly override, fixes #481
This commit is contained in:
parent
6d1a9e589c
commit
2cf4c3cd7b
|
@ -46,8 +46,8 @@ export class OpenAPIParser {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
spec: OpenAPISpec,
|
spec: OpenAPISpec,
|
||||||
specUrl: string | undefined,
|
specUrl?: string,
|
||||||
private options: RedocNormalizedOptions,
|
private options: RedocNormalizedOptions = new RedocNormalizedOptions({}),
|
||||||
) {
|
) {
|
||||||
this.validate(spec);
|
this.validate(spec);
|
||||||
this.preprocess(spec);
|
this.preprocess(spec);
|
||||||
|
@ -166,6 +166,13 @@ export class OpenAPIParser {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shalowDeref<T extends object>(obj: OpenAPIRef | T): T {
|
||||||
|
if (this.isRef(obj)) {
|
||||||
|
return this.byRef<T>(obj.$ref)!;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge allOf contsraints.
|
* Merge allOf contsraints.
|
||||||
* @param schema schema with allOF
|
* @param schema schema with allOF
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
getOperationSummary,
|
getOperationSummary,
|
||||||
isAbsolutePath,
|
isAbsolutePath,
|
||||||
JsonPointer,
|
JsonPointer,
|
||||||
|
mergeParams,
|
||||||
sortByRequired,
|
sortByRequired,
|
||||||
stripTrailingSlash,
|
stripTrailingSlash,
|
||||||
} from '../../utils';
|
} from '../../utils';
|
||||||
|
@ -65,7 +66,9 @@ export class OperationModel implements IMenuItem {
|
||||||
this.id =
|
this.id =
|
||||||
operationSpec.operationId !== undefined
|
operationSpec.operationId !== undefined
|
||||||
? 'operation/' + operationSpec.operationId
|
? 'operation/' + operationSpec.operationId
|
||||||
: this.parent !== undefined ? this.parent.id + operationSpec._$ref : operationSpec._$ref;
|
: this.parent !== undefined
|
||||||
|
? this.parent.id + operationSpec._$ref
|
||||||
|
: operationSpec._$ref;
|
||||||
|
|
||||||
this.name = getOperationSummary(operationSpec);
|
this.name = getOperationSummary(operationSpec);
|
||||||
this.description = operationSpec.description;
|
this.description = operationSpec.description;
|
||||||
|
@ -83,9 +86,11 @@ export class OperationModel implements IMenuItem {
|
||||||
this.codeSamples = operationSpec['x-code-samples'] || [];
|
this.codeSamples = operationSpec['x-code-samples'] || [];
|
||||||
this.path = JsonPointer.baseName(this._$ref, 2);
|
this.path = JsonPointer.baseName(this._$ref, 2);
|
||||||
|
|
||||||
this.parameters = operationSpec.pathParameters
|
this.parameters = mergeParams(
|
||||||
.concat(operationSpec.parameters || [])
|
parser,
|
||||||
.map(paramOrRef => new FieldModel(parser, paramOrRef, this._$ref, options));
|
operationSpec.pathParameters,
|
||||||
|
operationSpec.parameters,
|
||||||
|
).map(paramOrRef => new FieldModel(parser, paramOrRef, this._$ref, options));
|
||||||
|
|
||||||
if (options.requiredPropsFirst) {
|
if (options.requiredPropsFirst) {
|
||||||
sortByRequired(this.parameters);
|
sortByRequired(this.parameters);
|
||||||
|
|
|
@ -4,8 +4,12 @@ import {
|
||||||
getStatusCodeType,
|
getStatusCodeType,
|
||||||
isOperationName,
|
isOperationName,
|
||||||
isPrimitiveType,
|
isPrimitiveType,
|
||||||
|
mergeParams,
|
||||||
} from '../';
|
} from '../';
|
||||||
|
|
||||||
|
import { OpenAPIParser } from '../../services';
|
||||||
|
import { OpenAPIParameter } from '../../types';
|
||||||
|
|
||||||
describe('Utils', () => {
|
describe('Utils', () => {
|
||||||
describe('openapi getStatusCode', () => {
|
describe('openapi getStatusCode', () => {
|
||||||
it('Should return info for status codes within 100 and 200', () => {
|
it('Should return info for status codes within 100 and 200', () => {
|
||||||
|
@ -183,4 +187,39 @@ describe('Utils', () => {
|
||||||
expect(isPrimitiveType(schema)).toEqual(false);
|
expect(isPrimitiveType(schema)).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('openapi mergeParams', () => {
|
||||||
|
it('Should deduplicate params with same "name" and "in"', () => {
|
||||||
|
const pathParams: OpenAPIParameter[] = [
|
||||||
|
{
|
||||||
|
name: 'param1',
|
||||||
|
in: 'path',
|
||||||
|
description: 'path',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'param2',
|
||||||
|
in: 'path',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const operationParams: OpenAPIParameter[] = [
|
||||||
|
{
|
||||||
|
name: 'param1',
|
||||||
|
in: 'path',
|
||||||
|
description: 'oper',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'param2',
|
||||||
|
in: 'query',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const parser = new OpenAPIParser({ openapi: '3.0' } as any);
|
||||||
|
|
||||||
|
const res = mergeParams(parser, pathParams, operationParams) as OpenAPIParameter[];
|
||||||
|
expect(res).toHaveLength(3);
|
||||||
|
expect(res[0]).toEqual(pathParams[1]);
|
||||||
|
expect(res[1]).toEqual(operationParams[0]);
|
||||||
|
expect(res[2]).toEqual(operationParams[1]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { OpenAPIOperation, OpenAPISchema } from '../types';
|
import { OpenAPIParser } from '../services/OpenAPIParser';
|
||||||
|
import { OpenAPIOperation, OpenAPIParameter, OpenAPISchema, Referenced } from '../types';
|
||||||
|
|
||||||
export function getStatusCodeType(statusCode: string | number, defaultAsError = false): string {
|
export function getStatusCodeType(statusCode: string | number, defaultAsError = false): string {
|
||||||
if (statusCode === 'default') {
|
if (statusCode === 'default') {
|
||||||
|
@ -178,4 +179,24 @@ export function sortByRequired(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mergeParams(
|
||||||
|
parser: OpenAPIParser,
|
||||||
|
pathParams: Array<Referenced<OpenAPIParameter>> = [],
|
||||||
|
operationParams: Array<Referenced<OpenAPIParameter>> = [],
|
||||||
|
): Array<Referenced<OpenAPIParameter>> {
|
||||||
|
const operationParamNames = {};
|
||||||
|
operationParams.forEach(param => {
|
||||||
|
param = parser.shalowDeref(param);
|
||||||
|
operationParamNames[param.name + '_' + param.in] = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// filter out path params overriden by operation ones with the same name
|
||||||
|
pathParams = pathParams.filter(param => {
|
||||||
|
param = parser.shalowDeref(param);
|
||||||
|
return !operationParamNames[param.name + '_' + param.in];
|
||||||
|
});
|
||||||
|
|
||||||
|
return pathParams.concat(operationParams);
|
||||||
|
}
|
||||||
|
|
||||||
export const SECURITY_SCHEMES_SECTION = 'section/Authentication/';
|
export const SECURITY_SCHEMES_SECTION = 'section/Authentication/';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user