Ask a Question

How to swagger annotate multipart form data with resteasy?

gpreston
Regular Visitor

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 1
frantuma
Staff

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
cancel
Showing results for 
Search instead for 
Did you mean: