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

Arrays are parsed incorrectly with multipart/form-data #1869

Closed
alfechner opened this issue Feb 9, 2024 · 1 comment · Fixed by #1872
Closed

Arrays are parsed incorrectly with multipart/form-data #1869

alfechner opened this issue Feb 9, 2024 · 1 comment · Fixed by #1872

Comments

@alfechner
Copy link
Contributor

Description

I use multipart/form-data with a property bar which is of type array. The encoding is set to application/json. The spec looks like this:

openapi: 3.0.3
info:
  title: LIQUID Dataset Service
  version: 1.0.0
paths:
  /foo:
    post:
      x-openapi-router-controller: liquid_dataset_service.controllers.dataset_controller
      operationId: create_bar
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                bar:
                  type: array
                  items:
                    type: object
                    properties:
                      baz:
                        type: string
              required:
                - bar
            encoding:
              bar:
                contentType: application/json
      responses:
        204:
          description: No Content

Expected behaviour

When running the request I'd expect to get the bar property passed into the body argument of my controller function.

Actual behaviour

Server raises error: Validation error: '["{\\n \\"baz\\": \\"string\\"\\n}"]' is not of type 'object' - 'bar.0'.

To me it looks like that the string is not properly parsed if it's an array. To verify I changed the type of bar from array of object's to array of string's:

bar:
  type: array
  items:
    type: string

I passed two strings "one" and "two" and received this dict in my controller function: {'bar': ['["one"', '"two"]']}.

Steps to reproduce

Create a controller function, e.g.:

def create_bar(body):
    return

Adjust property x-openapi-router-controller accordingly.

Fire up the swagger page or use curl to run the request.

Additional info:

Output of the commands:

  • python --version: Python 3.11.6
  • pip show connexion | grep "^Version\:": Version: 3.0.5
@alfechner
Copy link
Contributor Author

alfechner commented Feb 9, 2024

I found the resolve_form method invoked from

data = self._uri_parser.resolve_form(form_data)

It's splitting the string parsed from the form data:

if defn and defn["type"] == "array":
form_data[k] = self._split(form_data[k], encoding, "form")
elif "contentType" in encoding and all_json([encoding.get("contentType")]):
form_data[k] = json.loads(form_data[k])

In my example form_data[k] is '["one","two"]' and self._split returns '["one"', '"two"]' instead of leaving it to the elif which correctly parses the JSON array.

I guess the splitting is place for URI params?

Shouldn't we always use json.loads(form_data[k]) if the encoding is set to application/json?

Maybe it's enough to switch the if with the elif and check for the content type first?

Would really appreciate feedback since our team is blocked by this 😅

RobbeSneyders pushed a commit that referenced this issue Feb 13, 2024
Fixes #1869 .



Changes proposed in this pull request:

- Prioritise parsing JSON over splitting array

---------

Co-authored-by: Alex Fechner <alex.fechner@stryker.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant