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(http): Handle undefined serialized JSON Query param #2844

Conversation

acote-coveo
Copy link
Contributor

@acote-coveo acote-coveo commented Feb 16, 2023

Description

When a query parameter has content-type like JSON, an undefined serialized value could result into a Javascript Runtime error.

If we look at the code, we can see that if the parameter has a content property, we have the following handling:

if (parameter.content) {
const effectiveMediaType = Object.keys(parameter.content)[0];
req.query[parameter.name] = serialize(value, effectiveMediaType);
return;
}

Then, if look into the serialize function, we see that for JSON, it will either serialize the value or return it (if it's a string:

export default function serialize(value, mediaType) {
if (mediaType.includes('application/json')) {
if (typeof value === 'string') {
// Assume the user has a JSON string
return value;
}
return JSON.stringify(value);
}
return value.toString();
}

The JSON.stringify() was returning an undefined value if it was provided with a undefined value. Thus, it was breaking a bunch of assumptions in the code to expect the value to be an object or a string.

Motivation and Context

Whenever we would define a query parameter of content type "application/json", if no value or example was provided for this value, it will result in a runtime error. Consequently, we were able to use the Try it out feature of Swagger UI on the endpoints having this particularity.

It potentially fixes swagger-api/swagger-ui#8374. I haven't tested but it the same error.

How Has This Been Tested?

I added unit test to see if the error still happen and I tested the change locally by linking my local instance of SwaggerUI with my local SwaggerClient repo.

I made sure there was no JS error when trying an endpoint and made sure the parameter were properly passed.

Screenshots (if appropriate):

Types of changes

  • No code changes (changes to documentation, CI, metadata, etc)
  • Dependency changes (any modification to dependencies in package.json)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

When a query parameter has content-type like JSON, an undefined serialized value could result into a Javascript Runtime error. This change will handle undefined value and simply ignore it.
@char0n char0n self-requested a review February 16, 2023 17:47
@char0n char0n self-assigned this Feb 16, 2023
@char0n
Copy link
Member

char0n commented Feb 17, 2023

Hi @acote-coveo,

Thanks for contributing I'll look in this PR ASAP.

@char0n
Copy link
Member

char0n commented Feb 22, 2023

This will be processed when [email protected] (https://github.com/swagger-api/swagger-js/releases/tag/v3.19.0-beta.5) is out of beta, probably during next week. The timing needs to be sequential here.

@char0n
Copy link
Member

char0n commented Mar 6, 2023

All right, we're in stable release channel again, I'll process this PR during this week.


if (serializedValue) {
req.query[parameter.name] = serializedValue;
} else if (parameter.allowEmptyValue && value !== undefined) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This else block is AFAICT never going to be hit. If we look at serialize function:

export default function serialize(value, mediaType) {
  if (mediaType.includes('application/json')) {
    if (typeof value === 'string') {
      // Assume the user has a JSON string
      return value;
    }
    return JSON.stringify(value);
  }

  return value.toString();
}

If always returns undefined or string. It returns undefined for following cases:

serialize(undefined, 'application/json'); // => undefined
serialize(Symbol.for('test'), 'application/json'); // => undefined
...etc...

We've now established that the serializedValue variable can be either string or undefined, this serves as a proof that else is never going to be hit.

What do you think, if we would simplify the code into following statement?

  if (parameter.content) {
    const effectiveMediaType = Object.keys(parameter.content)[0];

    value = serialize(value, effectiveMediaType);
    if (value) {
      req.query[parameter.name] = value;
    }
    return;
  }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've now established that the serializedValue variable can be either string or undefined, this serves as a proof that else is never going to be hit.

The else if is comparing the value to undefined. So the simplification you're suggesting is not entirely equivalent.

Take this example:

const value = Symbol.for('test') // Symbol(test)
serialize(value, 'application/json'); // undefined

// Invalidation of your proof
value !== undefined // true

Note that I haven't look at all the possible combination of input/output we could have for the serialize functional. So I took the safest path and kept the same else that I saw elsewhere in the code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, we're comparing serializedValue and value. So taking my falsy "elaboration" back.

test/client.js Outdated Show resolved Hide resolved
Co-authored-by: Vladimír Gorej <[email protected]>
@char0n char0n merged commit 285ade8 into swagger-api:master Mar 8, 2023
swagger-bot pushed a commit that referenced this pull request Mar 8, 2023
## [3.19.1](v3.19.0...v3.19.1) (2023-03-08)

### Bug Fixes

* **execute:** handle undefined serialized JSON Query param ([#2844](#2844)) ([285ade8](285ade8))
@swagger-bot
Copy link
Contributor

🎉 This PR is included in version 3.19.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Rendering of nested objects break when using allOf in the main schema
3 participants