mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-29 20:13:43 +03:00
fix: serialize parameter example values according to the spec (#917)
This commit is contained in:
parent
888f04e872
commit
39392869f4
|
@ -154,7 +154,8 @@
|
||||||
"slugify": "^1.3.4",
|
"slugify": "^1.3.4",
|
||||||
"stickyfill": "^1.1.1",
|
"stickyfill": "^1.1.1",
|
||||||
"swagger2openapi": "^5.2.3",
|
"swagger2openapi": "^5.2.3",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3",
|
||||||
|
"uri-template-lite": "^19.4.0"
|
||||||
},
|
},
|
||||||
"bundlesize": [
|
"bundlesize": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { ExampleValue, FieldLabel } from '../../common-elements/fields';
|
||||||
export interface FieldDetailProps {
|
export interface FieldDetailProps {
|
||||||
value?: any;
|
value?: any;
|
||||||
label: string;
|
label: string;
|
||||||
|
raw?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FieldDetail extends React.PureComponent<FieldDetailProps> {
|
export class FieldDetail extends React.PureComponent<FieldDetailProps> {
|
||||||
|
@ -11,11 +12,14 @@ export class FieldDetail extends React.PureComponent<FieldDetailProps> {
|
||||||
if (this.props.value === undefined) {
|
if (this.props.value === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const value = this.props.raw ? this.props.value : JSON.stringify(this.props.value);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FieldLabel> {this.props.label} </FieldLabel>{' '}
|
<FieldLabel> {this.props.label} </FieldLabel>{' '}
|
||||||
<ExampleValue>
|
<ExampleValue>
|
||||||
{JSON.stringify(this.props.value)}
|
{value}
|
||||||
</ExampleValue>
|
</ExampleValue>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
TypePrefix,
|
TypePrefix,
|
||||||
TypeTitle,
|
TypeTitle,
|
||||||
} from '../../common-elements/fields';
|
} from '../../common-elements/fields';
|
||||||
|
import { serializeParameterValue } from '../../utils/openapi';
|
||||||
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
import { EnumValues } from './EnumValues';
|
import { EnumValues } from './EnumValues';
|
||||||
|
@ -27,6 +28,18 @@ export class FieldDetails extends React.PureComponent<FieldProps> {
|
||||||
|
|
||||||
const { schema, description, example, deprecated } = field;
|
const { schema, description, example, deprecated } = field;
|
||||||
|
|
||||||
|
let exampleField: JSX.Element | null = null;
|
||||||
|
|
||||||
|
if (showExamples) {
|
||||||
|
const label = l('example') + ':';
|
||||||
|
if (field.in && field.style) {
|
||||||
|
const serializedValue = serializeParameterValue(field, example);
|
||||||
|
exampleField = <FieldDetail label={label} value={serializedValue} raw={true} />;
|
||||||
|
} else {
|
||||||
|
exampleField = <FieldDetail label={label} value={example} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -53,7 +66,7 @@ export class FieldDetails extends React.PureComponent<FieldProps> {
|
||||||
)}
|
)}
|
||||||
<FieldDetail label={l('default') + ':'} value={schema.default} />
|
<FieldDetail label={l('default') + ':'} value={schema.default} />
|
||||||
{!renderDiscriminatorSwitch && <EnumValues type={schema.type} values={schema.enum} />}{' '}
|
{!renderDiscriminatorSwitch && <EnumValues type={schema.type} values={schema.enum} />}{' '}
|
||||||
{showExamples && <FieldDetail label={l('example') + ':'} value={example} />}
|
{exampleField}
|
||||||
{<Extensions extensions={{ ...field.extensions, ...schema.extensions }} />}
|
{<Extensions extensions={{ ...field.extensions, ...schema.extensions }} />}
|
||||||
<div>
|
<div>
|
||||||
<Markdown compact={true} source={description} />
|
<Markdown compact={true} source={description} />
|
||||||
|
|
|
@ -10,6 +10,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
"description": "",
|
"description": "",
|
||||||
"example": undefined,
|
"example": undefined,
|
||||||
"expanded": false,
|
"expanded": false,
|
||||||
|
"explode": false,
|
||||||
"in": undefined,
|
"in": undefined,
|
||||||
"kind": "field",
|
"kind": "field",
|
||||||
"name": "packSize",
|
"name": "packSize",
|
||||||
|
@ -59,6 +60,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
"description": "",
|
"description": "",
|
||||||
"example": undefined,
|
"example": undefined,
|
||||||
"expanded": false,
|
"expanded": false,
|
||||||
|
"explode": false,
|
||||||
"in": undefined,
|
"in": undefined,
|
||||||
"kind": "field",
|
"kind": "field",
|
||||||
"name": "type",
|
"name": "type",
|
||||||
|
|
|
@ -10,6 +10,13 @@
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"name": "test_name",
|
"name": "test_name",
|
||||||
"schema": { "type": "string" }
|
"schema": { "type": "string" }
|
||||||
|
},
|
||||||
|
"serializationParam": {
|
||||||
|
"in": "query",
|
||||||
|
"name": "serialization_test_name",
|
||||||
|
"schema": { "type": "array" },
|
||||||
|
"style": "form",
|
||||||
|
"explode": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
|
|
|
@ -26,6 +26,23 @@ describe('Models', () => {
|
||||||
expect(field.schema.type).toEqual('string');
|
expect(field.schema.type).toEqual('string');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('field details relevant for parameter serialization', () => {
|
||||||
|
const field = new FieldModel(
|
||||||
|
parser,
|
||||||
|
{
|
||||||
|
$ref: '#/components/parameters/serializationParam',
|
||||||
|
},
|
||||||
|
'#/components/parameters/serializationParam',
|
||||||
|
opts,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(field.name).toEqual('serialization_test_name');
|
||||||
|
expect(field.in).toEqual('query');
|
||||||
|
expect(field.schema.type).toEqual('array');
|
||||||
|
expect(field.style).toEqual('form');
|
||||||
|
expect(field.explode).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
test('field name should populated from name even if $ref (headers)', () => {
|
test('field name should populated from name even if $ref (headers)', () => {
|
||||||
const field = new FieldModel(
|
const field = new FieldModel(
|
||||||
parser,
|
parser,
|
||||||
|
|
|
@ -1,12 +1,30 @@
|
||||||
import { action, observable } from 'mobx';
|
import { action, observable } from 'mobx';
|
||||||
|
|
||||||
import { OpenAPIParameter, Referenced } from '../../types';
|
import {
|
||||||
|
OpenAPIParameter,
|
||||||
|
OpenAPIParameterLocation,
|
||||||
|
OpenAPIParameterStyle,
|
||||||
|
Referenced,
|
||||||
|
} from '../../types';
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
|
|
||||||
import { extractExtensions } from '../../utils/openapi';
|
import { extractExtensions } from '../../utils/openapi';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
import { SchemaModel } from './Schema';
|
import { SchemaModel } from './Schema';
|
||||||
|
|
||||||
|
function getDefaultStyleValue(parameterLocation: OpenAPIParameterLocation): OpenAPIParameterStyle {
|
||||||
|
switch (parameterLocation) {
|
||||||
|
case 'header':
|
||||||
|
return 'simple';
|
||||||
|
case 'query':
|
||||||
|
return 'form';
|
||||||
|
case 'path':
|
||||||
|
return 'simple';
|
||||||
|
default:
|
||||||
|
return 'form';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field or Parameter model ready to be used by components
|
* Field or Parameter model ready to be used by components
|
||||||
*/
|
*/
|
||||||
|
@ -20,9 +38,11 @@ export class FieldModel {
|
||||||
description: string;
|
description: string;
|
||||||
example?: string;
|
example?: string;
|
||||||
deprecated: boolean;
|
deprecated: boolean;
|
||||||
in?: string;
|
in?: OpenAPIParameterLocation;
|
||||||
kind: string;
|
kind: string;
|
||||||
extensions?: Dict<any>;
|
extensions?: Dict<any>;
|
||||||
|
explode: boolean;
|
||||||
|
style?: OpenAPIParameterStyle;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
parser: OpenAPIParser,
|
parser: OpenAPIParser,
|
||||||
|
@ -40,6 +60,14 @@ export class FieldModel {
|
||||||
info.description === undefined ? this.schema.description || '' : info.description;
|
info.description === undefined ? this.schema.description || '' : info.description;
|
||||||
this.example = info.example || this.schema.example;
|
this.example = info.example || this.schema.example;
|
||||||
|
|
||||||
|
if (info.style) {
|
||||||
|
this.style = info.style;
|
||||||
|
} else if (this.in) {
|
||||||
|
this.style = getDefaultStyleValue(this.in);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.explode = !!info.explode;
|
||||||
|
|
||||||
this.deprecated = info.deprecated === undefined ? !!this.schema.deprecated : info.deprecated;
|
this.deprecated = info.deprecated === undefined ? !!this.schema.deprecated : info.deprecated;
|
||||||
parser.exitRef(infoOrRef);
|
parser.exitRef(infoOrRef);
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,11 @@ import {
|
||||||
mergeParams,
|
mergeParams,
|
||||||
normalizeServers,
|
normalizeServers,
|
||||||
pluralizeType,
|
pluralizeType,
|
||||||
|
serializeParameterValue,
|
||||||
} from '../';
|
} from '../';
|
||||||
|
|
||||||
import { OpenAPIParser } from '../../services';
|
import { OpenAPIParser } from '../../services';
|
||||||
import { OpenAPIParameter } from '../../types';
|
import { OpenAPIParameter, OpenAPIParameterLocation, OpenAPIParameterStyle } from '../../types';
|
||||||
|
|
||||||
describe('Utils', () => {
|
describe('Utils', () => {
|
||||||
describe('openapi getStatusCode', () => {
|
describe('openapi getStatusCode', () => {
|
||||||
|
@ -377,4 +378,190 @@ describe('Utils', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('openapi serializeParameter', () => {
|
||||||
|
interface TestCase {
|
||||||
|
style: OpenAPIParameterStyle;
|
||||||
|
explode: boolean;
|
||||||
|
expected: string;
|
||||||
|
}
|
||||||
|
interface TestValueTypeGroup {
|
||||||
|
value: any;
|
||||||
|
description: string;
|
||||||
|
cases: TestCase[];
|
||||||
|
}
|
||||||
|
interface TestLocationGroup {
|
||||||
|
location: OpenAPIParameterLocation;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
cases: TestValueTypeGroup[];
|
||||||
|
}
|
||||||
|
const testCases: TestLocationGroup[] = [
|
||||||
|
{
|
||||||
|
location: 'path',
|
||||||
|
name: 'id',
|
||||||
|
description: 'path parameters',
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
value: 5,
|
||||||
|
description: 'primitive values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'simple', explode: false, expected: '5' },
|
||||||
|
{ style: 'simple', explode: true, expected: '5' },
|
||||||
|
{ style: 'label', explode: false, expected: '.5' },
|
||||||
|
{ style: 'label', explode: true, expected: '.5' },
|
||||||
|
{ style: 'matrix', explode: false, expected: ';id=5' },
|
||||||
|
{ style: 'matrix', explode: true, expected: ';id=5' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: [3, 4, 5],
|
||||||
|
description: 'array values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'simple', explode: false, expected: '3,4,5' },
|
||||||
|
{ style: 'simple', explode: true, expected: '3,4,5' },
|
||||||
|
{ style: 'label', explode: false, expected: '.3,4,5' },
|
||||||
|
{ style: 'label', explode: true, expected: '.3.4.5' },
|
||||||
|
{ style: 'matrix', explode: false, expected: ';id=3,4,5' },
|
||||||
|
{ style: 'matrix', explode: true, expected: ';id=3;id=4;id=5' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: { role: 'admin', firstName: 'Alex' },
|
||||||
|
description: 'object values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'simple', explode: false, expected: 'role,admin,firstName,Alex' },
|
||||||
|
{ style: 'simple', explode: true, expected: 'role=admin,firstName=Alex' },
|
||||||
|
{ style: 'label', explode: false, expected: '.role,admin,firstName,Alex' },
|
||||||
|
{ style: 'label', explode: true, expected: '.role=admin,firstName=Alex' },
|
||||||
|
{ style: 'matrix', explode: false, expected: ';id=role,admin,firstName,Alex' },
|
||||||
|
{ style: 'matrix', explode: true, expected: ';role=admin;firstName=Alex' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
location: 'query',
|
||||||
|
name: 'id',
|
||||||
|
description: 'query parameters',
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
value: 5,
|
||||||
|
description: 'primitive values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'form', explode: true, expected: 'id=5' },
|
||||||
|
{ style: 'form', explode: false, expected: 'id=5' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: [3, 4, 5],
|
||||||
|
description: 'array values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'form', explode: true, expected: 'id=3&id=4&id=5' },
|
||||||
|
{ style: 'form', explode: false, expected: 'id=3,4,5' },
|
||||||
|
{ style: 'spaceDelimited', explode: true, expected: 'id=3&id=4&id=5' },
|
||||||
|
{ style: 'spaceDelimited', explode: false, expected: 'id=3%204%205' },
|
||||||
|
{ style: 'pipeDelimited', explode: true, expected: 'id=3&id=4&id=5' },
|
||||||
|
{ style: 'pipeDelimited', explode: false, expected: 'id=3|4|5' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: { role: 'admin', firstName: 'Alex' },
|
||||||
|
description: 'object values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'form', explode: true, expected: 'role=admin&firstName=Alex' },
|
||||||
|
{ style: 'form', explode: false, expected: 'id=role,admin,firstName,Alex' },
|
||||||
|
{ style: 'deepObject', explode: true, expected: 'id[role]=admin&id[firstName]=Alex' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
location: 'cookie',
|
||||||
|
name: 'id',
|
||||||
|
description: 'cookie parameters',
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
value: 5,
|
||||||
|
description: 'primitive values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'form', explode: true, expected: 'id=5' },
|
||||||
|
{ style: 'form', explode: false, expected: 'id=5' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: [3, 4, 5],
|
||||||
|
description: 'array values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'form', explode: true, expected: 'id=3&id=4&id=5' },
|
||||||
|
{ style: 'form', explode: false, expected: 'id=3,4,5' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: { role: 'admin', firstName: 'Alex' },
|
||||||
|
description: 'object values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'form', explode: true, expected: 'role=admin&firstName=Alex' },
|
||||||
|
{ style: 'form', explode: false, expected: 'id=role,admin,firstName,Alex' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
location: 'header',
|
||||||
|
name: 'id',
|
||||||
|
description: 'header parameters',
|
||||||
|
cases: [
|
||||||
|
{
|
||||||
|
value: 5,
|
||||||
|
description: 'primitive values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'simple', explode: false, expected: '5' },
|
||||||
|
{ style: 'simple', explode: true, expected: '5' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: [3, 4, 5],
|
||||||
|
description: 'array values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'simple', explode: false, expected: '3,4,5' },
|
||||||
|
{ style: 'simple', explode: true, expected: '3,4,5' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: { role: 'admin', firstName: 'Alex' },
|
||||||
|
description: 'object values',
|
||||||
|
cases: [
|
||||||
|
{ style: 'simple', explode: false, expected: 'role,admin,firstName,Alex' },
|
||||||
|
{ style: 'simple', explode: true, expected: 'role=admin,firstName=Alex' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
testCases.forEach(locationTestGroup => {
|
||||||
|
describe(locationTestGroup.description, () => {
|
||||||
|
locationTestGroup.cases.forEach(valueTypeTestGroup => {
|
||||||
|
describe(valueTypeTestGroup.description, () => {
|
||||||
|
valueTypeTestGroup.cases.forEach(testCase => {
|
||||||
|
it(`should serialize correctly when style is ${testCase.style} and explode is ${
|
||||||
|
testCase.explode
|
||||||
|
}`, () => {
|
||||||
|
const parameter: OpenAPIParameter = {
|
||||||
|
name: locationTestGroup.name,
|
||||||
|
in: locationTestGroup.location,
|
||||||
|
style: testCase.style,
|
||||||
|
explode: testCase.explode,
|
||||||
|
};
|
||||||
|
const serialized = serializeParameterValue(parameter, valueTypeTestGroup.value);
|
||||||
|
|
||||||
|
expect(serialized).toEqual(testCase.expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { dirname } from 'path';
|
import { dirname } from 'path';
|
||||||
|
import { URI } from 'uri-template-lite';
|
||||||
|
|
||||||
import { OpenAPIParser } from '../services/OpenAPIParser';
|
import { OpenAPIParser } from '../services/OpenAPIParser';
|
||||||
import {
|
import {
|
||||||
|
@ -6,6 +7,7 @@ import {
|
||||||
OpenAPIMediaType,
|
OpenAPIMediaType,
|
||||||
OpenAPIOperation,
|
OpenAPIOperation,
|
||||||
OpenAPIParameter,
|
OpenAPIParameter,
|
||||||
|
OpenAPIParameterStyle,
|
||||||
OpenAPISchema,
|
OpenAPISchema,
|
||||||
OpenAPIServer,
|
OpenAPIServer,
|
||||||
Referenced,
|
Referenced,
|
||||||
|
@ -135,36 +137,6 @@ export function isFormUrlEncoded(contentType: string): boolean {
|
||||||
return contentType === 'application/x-www-form-urlencoded';
|
return contentType === 'application/x-www-form-urlencoded';
|
||||||
}
|
}
|
||||||
|
|
||||||
function formEncodeField(fieldVal: any, fieldName: string, explode: boolean): string {
|
|
||||||
if (!fieldVal || !fieldVal.length) {
|
|
||||||
return fieldName + '=';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(fieldVal)) {
|
|
||||||
if (explode) {
|
|
||||||
return fieldVal.map(val => `${fieldName}=${val}`).join('&');
|
|
||||||
} else {
|
|
||||||
return fieldName + '=' + fieldVal.map(val => val.toString()).join(',');
|
|
||||||
}
|
|
||||||
} else if (typeof fieldVal === 'object') {
|
|
||||||
if (explode) {
|
|
||||||
return Object.keys(fieldVal)
|
|
||||||
.map(k => `${k}=${fieldVal[k]}`)
|
|
||||||
.join('&');
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
fieldName +
|
|
||||||
'=' +
|
|
||||||
Object.keys(fieldVal)
|
|
||||||
.map(k => `${k},${fieldVal[k]}`)
|
|
||||||
.join(',')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return fieldName + '=' + fieldVal.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function delimitedEncodeField(fieldVal: any, fieldName: string, delimeter: string): string {
|
function delimitedEncodeField(fieldVal: any, fieldName: string, delimeter: string): string {
|
||||||
if (Array.isArray(fieldVal)) {
|
if (Array.isArray(fieldVal)) {
|
||||||
return fieldVal.map(v => v.toString()).join(delimeter);
|
return fieldVal.map(v => v.toString()).join(delimeter);
|
||||||
|
@ -191,6 +163,13 @@ function deepObjectEncodeField(fieldVal: any, fieldName: string): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function serializeFormValue(name: string, explode: boolean, value: any) {
|
||||||
|
const suffix = explode ? '*' : '';
|
||||||
|
const template = new URI.Template(`{?${name}${suffix}}`);
|
||||||
|
|
||||||
|
return template.expand({ [name]: value }).substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Should be used only for url-form-encoded body payloads
|
* Should be used only for url-form-encoded body payloads
|
||||||
* To be used for parmaters should be extended with other style values
|
* To be used for parmaters should be extended with other style values
|
||||||
|
@ -208,7 +187,7 @@ export function urlFormEncodePayload(
|
||||||
const { style = 'form', explode = true } = encoding[fieldName] || {};
|
const { style = 'form', explode = true } = encoding[fieldName] || {};
|
||||||
switch (style) {
|
switch (style) {
|
||||||
case 'form':
|
case 'form':
|
||||||
return formEncodeField(fieldVal, fieldName, explode);
|
return serializeFormValue(fieldName, explode, fieldVal);
|
||||||
break;
|
break;
|
||||||
case 'spaceDelimited':
|
case 'spaceDelimited':
|
||||||
return delimitedEncodeField(fieldVal, fieldName, '%20');
|
return delimitedEncodeField(fieldVal, fieldName, '%20');
|
||||||
|
@ -226,6 +205,124 @@ export function urlFormEncodePayload(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function serializePathParameter(
|
||||||
|
name: string,
|
||||||
|
style: OpenAPIParameterStyle,
|
||||||
|
explode: boolean,
|
||||||
|
value: any,
|
||||||
|
): string {
|
||||||
|
const suffix = explode ? '*' : '';
|
||||||
|
let prefix = '';
|
||||||
|
|
||||||
|
if (style === 'label') {
|
||||||
|
prefix = '.';
|
||||||
|
} else if (style === 'matrix') {
|
||||||
|
prefix = ';';
|
||||||
|
}
|
||||||
|
|
||||||
|
const template = new URI.Template(`{${prefix}${name}${suffix}}`);
|
||||||
|
|
||||||
|
return template.expand({ [name]: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
function serializeQueryParameter(
|
||||||
|
name: string,
|
||||||
|
style: OpenAPIParameterStyle,
|
||||||
|
explode: boolean,
|
||||||
|
value: any,
|
||||||
|
): string {
|
||||||
|
switch (style) {
|
||||||
|
case 'form':
|
||||||
|
return serializeFormValue(name, explode, value);
|
||||||
|
case 'spaceDelimited':
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
console.warn('The style spaceDelimited is only applicable to arrays');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (explode) {
|
||||||
|
return serializeFormValue(name, explode, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${name}=${value.join('%20')}`;
|
||||||
|
case 'pipeDelimited':
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
console.warn('The style pipeDelimited is only applicable to arrays');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (explode) {
|
||||||
|
return serializeFormValue(name, explode, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${name}=${value.join('|')}`;
|
||||||
|
case 'deepObject':
|
||||||
|
if (!explode || Array.isArray(value) || typeof value !== 'object') {
|
||||||
|
console.warn('The style deepObject is only applicable for objects with expolde=true');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return deepObjectEncodeField(value, name);
|
||||||
|
default:
|
||||||
|
console.warn('Unexpected style for query: ' + style);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function serializeHeaderParameter(
|
||||||
|
name: string,
|
||||||
|
style: OpenAPIParameterStyle,
|
||||||
|
explode: boolean,
|
||||||
|
value: any,
|
||||||
|
): string {
|
||||||
|
switch (style) {
|
||||||
|
case 'simple':
|
||||||
|
const suffix = explode ? '*' : '';
|
||||||
|
const template = new URI.Template(`{${name}${suffix}}`);
|
||||||
|
|
||||||
|
return template.expand({ [name]: value });
|
||||||
|
default:
|
||||||
|
console.warn('Unexpected style for header: ' + style);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function serializeCookieParameter(
|
||||||
|
name: string,
|
||||||
|
style: OpenAPIParameterStyle,
|
||||||
|
explode: boolean,
|
||||||
|
value: any,
|
||||||
|
): string {
|
||||||
|
switch (style) {
|
||||||
|
case 'form':
|
||||||
|
return serializeFormValue(name, explode, value);
|
||||||
|
default:
|
||||||
|
console.warn('Unexpected style for cookie: ' + style);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serializeParameterValue(parameter: OpenAPIParameter, value: any): string {
|
||||||
|
const { name, style, explode = false } = parameter;
|
||||||
|
|
||||||
|
if (!style) {
|
||||||
|
console.warn(`Missing style attribute for parameter ${name}`);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (parameter.in) {
|
||||||
|
case 'path':
|
||||||
|
return serializePathParameter(name, style, explode, value);
|
||||||
|
case 'query':
|
||||||
|
return serializeQueryParameter(name, style, explode, value);
|
||||||
|
case 'header':
|
||||||
|
return serializeHeaderParameter(name, style, explode, value);
|
||||||
|
case 'cookie':
|
||||||
|
return serializeCookieParameter(name, style, explode, value);
|
||||||
|
default:
|
||||||
|
console.warn('Unexpected parameter location: ' + parameter.in);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function langFromMime(contentType: string): string {
|
export function langFromMime(contentType: string): string {
|
||||||
if (contentType.search(/xml/i) !== -1) {
|
if (contentType.search(/xml/i) !== -1) {
|
||||||
return 'xml';
|
return 'xml';
|
||||||
|
|
|
@ -9651,6 +9651,11 @@ uri-js@^4.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
|
uri-template-lite@^19.4.0:
|
||||||
|
version "19.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uri-template-lite/-/uri-template-lite-19.4.0.tgz#cbc2c072cf4931428a2f9d3aea36b8254a33cce5"
|
||||||
|
integrity sha512-VY8dgwyMwnCztkzhq0cA/YhNmO+YZqow//5FdmgE2fZU/JPi+U0rPL7MRDi0F+Ch4vJ7nYidWzeWAeY7uywe9g==
|
||||||
|
|
||||||
urix@^0.1.0:
|
urix@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user