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

Default Content-Type not applied to complex object parts in multipart/form-data #9548

Open
heguro opened this issue Feb 4, 2024 · 1 comment

Comments

@heguro
Copy link

heguro commented Feb 4, 2024

Q&A

  • OS: macOS
  • Browser: Firefox
  • Version: 122
  • Method of installation: swagger-ui-dist from unpkg
  • Swagger-UI version: 5.11.2
  • Swagger/OpenAPI version: OpenAPI 3.0.3

Content & configuration

Example Swagger/OpenAPI definition:

openapi: 3.0.3
servers:
- url: http://127.0.0.1:8080
paths:
  /profile:
    post:
      requestBody:
        content:
          multipart/form-data:
            schema:
              required:
              - address
              - id
              - profileImage
              type: object
              properties:
                id:
                  type: string
                address:
                  type: object
                  properties:
                    street:
                      type: string
                    city:
                      type: string
                profileImage:
                  type: string
                  format: binary
      responses:
        "200":
          description: OK

Swagger-UI configuration options:

SwaggerUIBundle({
  url: 'http://127.0.0.1:8080/api-docs.yaml',
  dom_id: '#swagger-ui',
  presets: [
    SwaggerUIBundle.presets.apis,
    SwaggerUIStandalonePreset
  ],
  layout: "StandaloneLayout",
})

Describe the bug you're encountering

According to the OpenAPI specification and the docs page, the default Content-Type for complex values (objects) in a multipart/form-data request should be application/json.
However, in the provided example, the address property, which is an object, does not have application/json as its Content-Type in the generated request and curl command.

Currently, it's possible to manually set encoding.address.contentType in the definition as application/json to generate the expected curl command (thanks to issue #5356 was fixed).
However, based on the OpenAPI specification, I believe type=application/json should automatically be applied even if encoding is not explicitly included in the definition.

To reproduce...

Steps to reproduce the behavior:

  1. Fill the blanks for the /profile request
  2. Click on 'Execute'
  3. Generated curl command and payload are:
curl -X 'POST' \
  'http://127.0.0.1:8080/profile' \
  -H 'accept: */*' \
  -H 'Content-Type: multipart/form-data' \
  -F 'id=string' \
  -F 'address={
  "street": "string",
  "city": "string"
}' \
  -F 'profileImage=@zerobyte.txt;type=text/plain'
-----------------------------306494087715324971512255078872
Content-Disposition: form-data; name="id"

string
-----------------------------306494087715324971512255078872
Content-Disposition: form-data; name="address"

{
  "street": "string",
  "city": "string"
}
-----------------------------306494087715324971512255078872
Content-Disposition: form-data; name="profileImage"; filename="zerobyte.txt"
Content-Type: text/plain


-----------------------------306494087715324971512255078872--

Expected behavior

 curl -X 'POST' \
   'http://127.0.0.1:8080/profile' \
   -H 'accept: */*' \
   -H 'Content-Type: multipart/form-data' \
   -F 'id=string' \
   -F 'address={
   "street": "string",
   "city": "string"
-}' \
+};type=application/json' \
   -F 'profileImage=@zerobyte.txt;type=text/plain'
 -----------------------------306494087715324971512255078872
 Content-Disposition: form-data; name="id"
 
 string
 -----------------------------306494087715324971512255078872
 Content-Disposition: form-data; name="address"
+Content-Type: application/json
 
 {
   "street": "string",
   "city": "string"
 }
 -----------------------------306494087715324971512255078872
 Content-Disposition: form-data; name="profileImage"; filename="zerobyte.txt"
 Content-Type: text/plain
 
 
 -----------------------------306494087715324971512255078872--

Additional context or thoughts

EDIT: this is part (maybe duplicate) of #6462

@Titou325
Copy link

Titou325 commented Mar 28, 2024

Also bumped into this issue with a mixed multipart/form-data payload containing both files and a JSON options object. It seems that adding the encoding[fieldName].contentType fixes the CURL call, however it also causes Swagger to send a filename: "blob" in the Content-Disposition header.

OK CURL command:

curl -X 'POST' \
  'http://localhost:3000/pdf/generate/' \
  -H 'accept: */*' \
  -H 'Content-Type: multipart/form-data' \
  -F 'options={
  "world": "string"
};type=application/json'

SwaggerUI request payload

------WebKitFormBoundarynwJpnsbiqaJv4Ljy
Content-Disposition: form-data; name="options"; filename="blob"
Content-Type: application/json

{
  "world": "string"
}
------WebKitFormBoundarynwJpnsbiqaJv4Ljy--

Notice the filename="blob" appended to the Content-Disposition header.

Expected

------WebKitFormBoundarynwJpnsbiqaJv4Ljy
Content-Disposition: form-data; name="options";
Content-Type: application/json

{
  "world": "string"
}
------WebKitFormBoundarynwJpnsbiqaJv4Ljy--

This causes subsequent multipart parsing to think of options as a file rather than an object.

I think we should at least have a coherent Curl command and Execute action. There may be multiple issues at play, setting Content-Type should probably not trigger an automatic filename although it was referenced as mandatory, and we shouldn't need to set up Content-Type for complex objects in the first place.

I will try to narrow down what is happening with the fetch request :)

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

No branches or pull requests

2 participants