Skip to content

Commit

Permalink
fix(execute): fix encoding of complex nested type values in OpenAPI 3…
Browse files Browse the repository at this point in the history
….x request builders

Refs swagger-api/swagger-ui#9755
  • Loading branch information
glowcloud authored Apr 5, 2024
2 parents 8128a09 + 131f377 commit 49ab957
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 34 deletions.
57 changes: 26 additions & 31 deletions src/execute/oas3/style-serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export function encodeDisallowedCharacters(str, { escape } = {}, parse) {
if (typeof str === 'number') {
str = str.toString();
}

if (typeof str !== 'string' || !str.length) {
return str;
}
Expand Down Expand Up @@ -55,23 +56,27 @@ export default function stylize(config) {
return encodePrimitive(config);
}

function encodeArray({ key, value, style, explode, escape }) {
const valueEncoder = (str) =>
encodeDisallowedCharacters(str, {
escape,
});
export function valueEncoder(value, escape) {
if (Array.isArray(value) || (value !== null && typeof value === 'object')) {
value = JSON.stringify(value);
}
return encodeDisallowedCharacters(value, {
escape,
});
}

function encodeArray({ key, value, style, explode, escape }) {
if (style === 'simple') {
return value.map((val) => valueEncoder(val)).join(',');
return value.map((val) => valueEncoder(val, escape)).join(',');
}

if (style === 'label') {
return `.${value.map((val) => valueEncoder(val)).join('.')}`;
return `.${value.map((val) => valueEncoder(val, escape)).join('.')}`;
}

if (style === 'matrix') {
return value
.map((val) => valueEncoder(val))
.map((val) => valueEncoder(val, escape))
.reduce((prev, curr) => {
if (!prev || explode) {
return `${prev || ''};${key}=${curr}`;
Expand All @@ -82,33 +87,28 @@ function encodeArray({ key, value, style, explode, escape }) {

if (style === 'form') {
const after = explode ? `&${key}=` : ',';
return value.map((val) => valueEncoder(val)).join(after);
return value.map((val) => valueEncoder(val, escape)).join(after);
}

if (style === 'spaceDelimited') {
const after = explode ? `${key}=` : '';
return value.map((val) => valueEncoder(val)).join(` ${after}`);
return value.map((val) => valueEncoder(val, escape)).join(` ${after}`);
}

if (style === 'pipeDelimited') {
const after = explode ? `${key}=` : '';
return value.map((val) => valueEncoder(val)).join(`|${after}`);
return value.map((val) => valueEncoder(val, escape)).join(`|${after}`);
}

return undefined;
}

function encodeObject({ key, value, style, explode, escape }) {
const valueEncoder = (str) =>
encodeDisallowedCharacters(str, {
escape,
});

const valueKeys = Object.keys(value);

if (style === 'simple') {
return valueKeys.reduce((prev, curr) => {
const val = valueEncoder(value[curr]);
const val = valueEncoder(value[curr], escape);
const middleChar = explode ? '=' : ',';
const prefix = prev ? `${prev},` : '';

Expand All @@ -118,7 +118,7 @@ function encodeObject({ key, value, style, explode, escape }) {

if (style === 'label') {
return valueKeys.reduce((prev, curr) => {
const val = valueEncoder(value[curr]);
const val = valueEncoder(value[curr], escape);
const middleChar = explode ? '=' : '.';
const prefix = prev ? `${prev}.` : '.';

Expand All @@ -128,7 +128,7 @@ function encodeObject({ key, value, style, explode, escape }) {

if (style === 'matrix' && explode) {
return valueKeys.reduce((prev, curr) => {
const val = valueEncoder(value[curr]);
const val = valueEncoder(value[curr], escape);
const prefix = prev ? `${prev};` : ';';

return `${prefix}${curr}=${val}`;
Expand All @@ -138,7 +138,7 @@ function encodeObject({ key, value, style, explode, escape }) {
if (style === 'matrix') {
// no explode
return valueKeys.reduce((prev, curr) => {
const val = valueEncoder(value[curr]);
const val = valueEncoder(value[curr], escape);
const prefix = prev ? `${prev},` : `;${key}=`;

return `${prefix}${curr},${val}`;
Expand All @@ -147,7 +147,7 @@ function encodeObject({ key, value, style, explode, escape }) {

if (style === 'form') {
return valueKeys.reduce((prev, curr) => {
const val = valueEncoder(value[curr]);
const val = valueEncoder(value[curr], escape);
const prefix = prev ? `${prev}${explode ? '&' : ','}` : '';
const separator = explode ? '=' : ',';

Expand All @@ -159,29 +159,24 @@ function encodeObject({ key, value, style, explode, escape }) {
}

function encodePrimitive({ key, value, style, escape }) {
const valueEncoder = (str) =>
encodeDisallowedCharacters(str, {
escape,
});

if (style === 'simple') {
return valueEncoder(value);
return valueEncoder(value, escape);
}

if (style === 'label') {
return `.${valueEncoder(value)}`;
return `.${valueEncoder(value, escape)}`;
}

if (style === 'matrix') {
return `;${key}=${valueEncoder(value)}`;
return `;${key}=${valueEncoder(value, escape)}`;
}

if (style === 'form') {
return valueEncoder(value);
return valueEncoder(value, escape);
}

if (style === 'deepObject') {
return valueEncoder(value, {}, true);
return valueEncoder(value, escape);
}

return undefined;
Expand Down
7 changes: 4 additions & 3 deletions src/http/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import qs from 'qs';
import jsYaml from 'js-yaml';

import '../helpers/fetch-polyfill.node.js';
import { encodeDisallowedCharacters } from '../execute/oas3/style-serializer.js';
import { valueEncoder } from '../execute/oas3/style-serializer.js';

// For testing
export const self = {
Expand Down Expand Up @@ -319,8 +319,9 @@ function formatKeyValueBySerializationOption(key, value, skipEncoding, serializa
: serializationOption && serializationOption.allowReserved
? 'unsafe'
: 'reserved';
const encodeFn = (v) => encodeDisallowedCharacters(v, { escape });
const encodeKeyFn = skipEncoding ? (k) => k : (k) => encodeDisallowedCharacters(k, { escape });

const encodeFn = (v) => valueEncoder(v, escape);
const encodeKeyFn = skipEncoding ? (k) => k : (k) => encodeFn(k);

// Primitive
if (typeof value !== 'object') {
Expand Down
Loading

0 comments on commit 49ab957

Please sign in to comment.