OpenAPITools / OpenAPITools/openapi-generator

[rust-server] Bug: Multipart requestBody string and file properties are parsed as base64 encoded JSON strings

Open
#13,307 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Description

Multipart requestBody string and file parameters are parsed as JSON base64 encoded strings, when instead they should be parsed as plain strings and binary data, respectively.

openapi-generator version

6.0.1

OpenAPI declaration file content or url
openapi: 3.0.1
info:
  title: TestAPI
  version: 1.0.0
paths:
  /the/endpoint:
    post:
      operationId: testOp
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - camelCase
              - file
              properties:
                camelCase:
                  type: string
                file:
                  type: string
                  format: binary
            encoding:
              camelCase:
                contentType: text/plain
              file:
                contentType: image/png
        required: true
      responses:
        200:
          description: Success
          content:
            application/json:
              schema:
                type: string
Command line used for generation

openapi-generator generate -g rust-server --enable-post-process-file --generate-alias-as-model

Steps to reproduce
  1. cargo run --example server
  2. curl -v -F camel_case=test -F file=@<test file> http://127.0.0.1:8080/the/endpoint
Suggest a fix/enhancement

Generated code works with the following patch, which I hope can suggest how to fix the generator:

--- mod.rs.orig	2022-08-29 15:16:09.135764200 +0200
+++ mod.rs.corrected	2022-08-29 15:39:35.299205700 +0200
@@ -175,10 +175,10 @@
                                 let param_camel_case = match field_camel_case {
                                     Some(field) => {
                                         let mut reader = field[0].data.readable().expect("Unable to read field for camel_case");
-                                        let mut data = String::new();
-                                        reader.read_to_string(&mut data).expect("Reading saved String should never fail");
-                                        let camel_case_model: String = match serde_json::from_str(&data) {
-                                            Ok(model) => model,
+                                        let mut data = Vec::new();
+                                        reader.read_to_end(&mut data).expect("Reading saved String should never fail");
+                                        let camel_case_model: String = match std::str::from_utf8(&data) {
+                                            Ok(model) => model.to_owned(),
                                             Err(e) => {
                                                 return Ok(
                                                     Response::builder()
@@ -201,19 +201,9 @@
                                 let param_file = match field_file {
                                     Some(field) => {
                                         let mut reader = field[0].data.readable().expect("Unable to read field for file");
-                                        let mut data = String::new();
-                                        reader.read_to_string(&mut data).expect("Reading saved String should never fail");
-                                        let file_model: swagger::ByteArray = match serde_json::from_str(&data) {
-                                            Ok(model) => model,
-                                            Err(e) => {
-                                                return Ok(
-                                                    Response::builder()
-                                                    .status(StatusCode::BAD_REQUEST)
-                                                    .body(Body::from(format!("file data does not match API definition : {}", e)))
-                                                    .expect("Unable to create Bad Request due to missing required form parameter file"))
-                                            }
-                                        };
-                                        file_model
+                                        let mut data = Vec::new();
+                                        reader.read_to_end(&mut data).expect("Reading saved String should never fail");
+                                        swagger::ByteArray(data)
                                     },
                                     None => {
                                         return Ok(

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the rust-server generator output from the provided OpenAPI declaration and reproduce the issue with cargo run --example server and the documented curl request. Compare the generated mod.rs multipart parsing with the suggested patch; done means string fields are read as plain text and binary file fields as raw bytes without JSON base64 parsing.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.