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

multipart/form-data arrays with one element are not sent as arrays #1728

Open
mottolini opened this issue Sep 22, 2020 · 1 comment
Open

Comments

@mottolini
Copy link

Q&A

  • Swagger-Client version: 3.10.2
  • Swagger/OpenAPI version: OpenAPI 3.0

Content & configuration

Swagger/OpenAPI definition:

paths:
  /test:
    post:
      requestBody:
        content:
          multipart/form-data:
            schema:
              title: Test
              type: object
              properties:
                photos:
                  type: array
                  items:
                    type: string
                    format: binary
      responses:
        "201":
          description: something

Describe the bug you're encountering

When you have a path definition of a multipart/form-data with a schema that contains an array and you pass just one element in this array, the backend receives a single value and not an array with just one element. This causes an exception by the openapi validator.
The problem lays in the function in the file http.js

function buildFormData(reqForm) {
  /**
   * Build a new FormData instance, support array as field value
   * OAS2.0 - when collectionFormat is multi
   * OAS3.0 - when explode of Encoding Object is true
   * @param {Object} reqForm - ori req.form
   * @return {FormData} - new FormData instance
   */
  return Object.entries(reqForm).reduce((formData, [name, input]) => {
    // eslint-disable-next-line no-restricted-syntax
    for (const [key, value] of formatKeyValue(name, input, true)) {
      if (Array.isArray(value)) {
        // eslint-disable-next-line no-restricted-syntax
        for (const v of value) {
          formData.append(key, v);
        }
      } else {
        formData.append(key, value);
      }
    }
    return formData;
  }, new FormData());
}

if in formData a fieldname is repeated more than once, then it is sent as an array, which is the actual behaviour of the function buildFormData. This curl, as an example, sends correctly photos as an array

curl --location --request POST 'http://localhost/route' \
--header 'Content-Type: multipart/form-data' \
--form '[email protected]' \
--form '[email protected]'

But, if you have just one element in your array, the equivalent curl "produced" by the function buildFormData just sends a single value and not an array

curl --location --request POST 'http://localhost/route' \
--header 'Content-Type: multipart/form-data' \
--form '[email protected]' 

The correct form to send an array is with the [] after the name of the field. The following curl sends an array even if there is just one element:

curl --location --request POST 'http://localhost/route' \
--header 'Content-Type: multipart/form-data' \
--form 'photos[][email protected]' 

How to fix it

The simplest way to fix it I think is to add '[]' to the name of the field in case it's an array:

function buildFormData(reqForm) {
  /**
   * Build a new FormData instance, support array as field value
   * OAS2.0 - when collectionFormat is multi
   * OAS3.0 - when explode of Encoding Object is true
   * @param {Object} reqForm - ori req.form
   * @return {FormData} - new FormData instance
   */
  return Object.entries(reqForm).reduce((formData, [name, input]) => {
    // eslint-disable-next-line no-restricted-syntax
    for (const [key, value] of formatKeyValue(name, input, true)) {
      if (Array.isArray(value)) {
        // eslint-disable-next-line no-restricted-syntax
        for (const v of value) {
          formData.append(key + '[]', v);
        }
      } else {
        formData.append(key, value);
      }
    }
    return formData;
  }, new FormData());
}
@char0n
Copy link
Member

char0n commented Sep 24, 2020

Hi @mottolini,

We'd welcome your PR with the fix. Please, along with the fix provide an accompanied test.

Update

Ah, OK I see that you already did ;]

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

Successfully merging a pull request may close this issue.

2 participants