Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(execute): refactor encodeDisallowedCharacters function #3463

Merged
merged 4 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/execute/oas3/parameter-builders.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import stylize, { encodeDisallowedCharacters } from './style-serializer.js';
import stylize, { encodeCharacters } from './style-serializer.js';
import serialize from './content-serializer.js';

export function path({ req, value, parameter }) {
Expand All @@ -11,7 +11,7 @@ export function path({ req, value, parameter }) {

req.url = req.url
.split(`{${name}}`)
.join(encodeDisallowedCharacters(serialize(value, effectiveMediaType), { escape: true }));
.join(encodeCharacters(serialize(value, effectiveMediaType)));
} else {
const styledValue = stylize({
key: parameter.name,
Expand Down
34 changes: 11 additions & 23 deletions src/execute/oas3/style-serializer.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
const isRfc3986Reserved = (char) => ":/?#[]@!$&'()*+,;=".indexOf(char) > -1;
const isRrc3986Unreserved = (char) => /^[a-z0-9\-._~]+$/i.test(char);
const isRfc3986Unreserved = (char) => /^[a-z0-9\-._~]+$/i.test(char);

// eslint-disable-next-line default-param-last
export function encodeDisallowedCharacters(str, { escape } = {}, parse) {
if (typeof str === 'number') {
str = str.toString();
}

if (typeof str !== 'string' || !str.length) {
return str;
}

if (!escape) {
return str;
}

if (parse) {
return JSON.parse(str);
}

export function encodeCharacters(str, { characterSet = 'reserved' } = {}) {
char0n marked this conversation as resolved.
Show resolved Hide resolved
// In ES6 you can do this quite easily by using the new ... spread operator.
// This causes the string iterator (another new ES6 feature) to be used internally,
// and because that iterator is designed to deal with
// code points rather than UCS-2/UTF-16 code units.
return [...str]
.map((char) => {
if (isRrc3986Unreserved(char)) {
if (isRfc3986Unreserved(char)) {
return char;
}

if (isRfc3986Reserved(char) && escape === 'unsafe') {
if (isRfc3986Reserved(char) && characterSet === 'unsafe') {
return char;
}

Expand Down Expand Up @@ -59,10 +43,14 @@ export default function stylize(config) {
export function valueEncoder(value, escape) {
char0n marked this conversation as resolved.
Show resolved Hide resolved
if (Array.isArray(value) || (value !== null && typeof value === 'object')) {
value = JSON.stringify(value);
} else if (typeof value === 'number' || typeof value === 'boolean') {
char0n marked this conversation as resolved.
Show resolved Hide resolved
value = value.toString();
char0n marked this conversation as resolved.
Show resolved Hide resolved
}

if (escape && value.length > 0) {
return encodeCharacters(value, escape === true ? {} : { characterSet: escape });
}
return encodeDisallowedCharacters(value, {
escape,
});
return value;
}

function encodeArray({ key, value, style, explode, escape }) {
Expand Down
10 changes: 5 additions & 5 deletions test/oas3/execute/style-serializer.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { encodeDisallowedCharacters } from '../../../src/execute/oas3/style-serializer.js';
import { valueEncoder } from '../../../src/execute/oas3/style-serializer.js';

describe('OAS3 style serializer', () => {
char0n marked this conversation as resolved.
Show resolved Hide resolved
describe('encodeDisallowedCharacters', () => {
describe('valueEncoder', () => {
test('should correctly encode ASCII characters', () => {
const tested = (str) => encodeDisallowedCharacters(str, { escape: true });
const tested = (str) => valueEncoder(str, true);

expect(tested('!')).toEqual('%21');
expect(tested('#')).toEqual('%23');
Expand All @@ -28,7 +28,7 @@ describe('OAS3 style serializer', () => {
});

test('should correctly encode non-ASCII characters', () => {
const tested = (str) => encodeDisallowedCharacters(str, { escape: true });
const tested = (str) => valueEncoder(str, true);
expect(tested('♥')).toEqual('%E2%99%A5');
expect(tested('テスト')).toEqual('%E3%83%86%E3%82%B9%E3%83%88');
expect(tested('𩸽')).toEqual('%F0%A9%B8%BD');
Expand All @@ -39,7 +39,7 @@ describe('OAS3 style serializer', () => {
});

test('should skip encoding if `escape` is not set to true', () => {
const tested = (str) => encodeDisallowedCharacters(str);
const tested = (str) => valueEncoder(str);

expect(tested('!')).toEqual('!');
expect(tested('#')).toEqual('#');
Expand Down