Forum Discussion

gpreston's avatar
gpreston
Regular Visitor
6 years ago

How to swagger annotate multipart form data with resteasy?

I'm attempting to annotate an endpoint in resteasy that is a multipart form upload.  One part is expected to be the stream of a file, and the other part is json metadata about the file.  Because we're using resteasy, the method parameter is a MultipartFormDataInput, which isn't very helpful for describing what the endpoint actually needs for input.

 

I've currently got annotations as follows:

 

  @POST
  @Path("/")
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  @Produces(MediaType.APPLICATION_JSON)
  @Operation(summary = "Upload a new image and associated metadata", description = "Long form description saying whatever we want",
          parameters = {
                  @Parameter(name = "file", description = "image file", required = true, style = ParameterStyle.FORM, content = {
                          @Content(mediaType = "application/pdf", schema = @Schema(type = "string", format = "binary")),
                          @Content(mediaType = "image/png", schema = @Schema(type = "string", format = "binary"))
                  }),
                  @Parameter(name = "metadata", description = "image metadata", required = true, style = ParameterStyle.FORM, content = {
                          @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = MetadataRequest.class))
                  })

          },
          responses = {
                  @ApiResponse(responseCode = "200", description = "The UUID of the newly uploaded image"),
                  @ApiResponse(responseCode = "403", description = "The provided credentials are insufficient to see this resource."),
                  @ApiResponse(responseCode = "415", description = "The provided file type is not supported"),
                  @ApiResponse(responseCode = "500", description = "We messed up. Please let us know so we can fix it ASAP.")

  })
  public PublicUploadResponse upload(@Parameter(hidden = true) MultipartFormDataInput form) {

for which swagger generates the following json

    "/v1/images" : {
      "post" : {
        "summary" : "Upload a new image and associated metadata",
        "description" : "Long form description saying whatever we want",
        "operationId" : "upload",
        "responses" : {
          "200" : {
            "description" : "The UUID of the newly uploaded image"
          },
          "403" : {
            "description" : "The provided credentials are insufficient to see this resource."
          },
          "415" : {
            "description" : "The provided file type is not supported"
          },
          "500" : {
            "description" : "We messed up. Please let us know so we can fix it ASAP."
          }
        }
      }
    },

As you can see, the parameter annotations are completely ignored.  I've tried moving the parameter annotations to the method, and that doesn't change anything.  We're using lastest swagger-core (2.0.6).

 

I just can't figure out why they are being ignored.  Any help or suggestions would be appreciated.

 

1 Reply

  • At the moment resteasy multi-part constructs are not supported out of the box as e.g jersey FormDataParam and the like (in this case specific framework annotations are resolved into the correct requestBody); while there is ongoing effort to add such support, in the meanwhile you would use something like the following to achieve what you need:

     

    @POST
    @Path("/")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.APPLICATION_JSON)
    @Operation(summary = "Upload a new image and associated metadata", description = "Long form description saying whatever we want",
    requestBody = @RequestBody(
    content = @Content(
    mediaType = "multipart/form-data",
    schema = @Schema(implementation = MultiRequest.class),
    encoding = @Encoding(
    name = "file",
    contentType = "application/pdf, image/png"
    )
    ))
    ,
    responses = {
    @ApiResponse(responseCode = "200", description = "The UUID of the newly uploaded image"),
    @ApiResponse(responseCode = "403", description = "The provided credentials are insufficient to see this resource."),
    @ApiResponse(responseCode = "415", description = "The provided file type is not supported"),
    @ApiResponse(responseCode = "500", description = "We messed up. Please let us know so we can fix it ASAP.")

    })
    public Response upload(@Parameter(hidden = true) MultipartFormDataInputImpl form) {
    return null;
    }


    // used solely in request body @Schema implementation
    class MultiRequest {
    @Schema(type = "string", format = "binary", description = "image file")
    public String file;
    @Schema(description = "image metadata")
    public MetadataRequest metadata;
    }

     

    this would resolve into:

     

    paths:
      /test:
        post:
          summary: Upload a new image and associated metadata
          description: Long form description saying whatever we want
          operationId: upload
          requestBody:
            content:
              multipart/form-data:
                schema:
                  $ref: '#/components/schemas/MultiRequest'
                encoding:
                  file:
                    contentType: application/pdf, image/png
          responses:
            200:
              description: The UUID of the newly uploaded image
            403:
              description: The provided credentials are insufficient to see this resource.
            415:
              description: The provided file type is not supported
            500:
              description: We messed up. Please let us know so we can fix it ASAP.
    components:
      schemas:
        MultiRequest:
          type: object
          properties:
            file:
              type: string
              description: image file
              format: binary
            metadata:
              $ref: '#/components/schemas/RequestMetadata'
        RequestMetadata:
          type: object
          properties:
            foo:
              type: string
          description: image metadata