OpenAPITools / OpenAPITools/openapi-generator

[BUG] [DART] Dart Generator does not generate Multipart properly. Sends an empty object instead of file

Open
#14,472 14 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue? Started from 6.0.0 (5.4.0 worked perfectly)
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

The Dart generator does not generate multipart properly. It sends an empty object instead of a multipart file provided.
It appears only with such configuration: dart-dio, json_serializable and timemachine.

If you use just a dart generator instead of dart-dio it generates it properly.

Here is an example of faulty outputs

Future<Response<UploadProfessionalImage201Response>> uploadProfessionalImage({ 
    required String professionalId,
    MultipartFile? image,
    CancelToken? cancelToken,
    Map<String, dynamic>? headers,
    Map<String, dynamic>? extra,
    ValidateStatus? validateStatus,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    final _path = r'/images/professionals/{professionalId}/'.replaceAll('{' r'professionalId' '}', professionalId.toString());
    final _options = Options(
      method: r'POST',
      headers: <String, dynamic>{
        ...?headers,
      },
      extra: <String, dynamic>{
        'secure': <Map<String, String>>[
          {
            'type': 'apiKey',
            'name': 'BearerToken',
            'keyName': 'Authorization',
            'where': 'header',
          },
        ],
        ...?extra,
      },
      contentType: 'multipart/form-data',
      validateStatus: validateStatus,
    );

    dynamic _bodyData;

    try {

    } catch(error, stackTrace) {
      throw DioError(
         requestOptions: _options.compose(
          _dio.options,
          _path,
        ),
        type: DioErrorType.other,
        error: error,
      )..stackTrace = stackTrace;
    }

    final _response = await _dio.request<Object>(
      _path,
      data: _bodyData,
      options: _options,
      cancelToken: cancelToken,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    );

    UploadProfessionalImage201Response _responseData;

    try {
_responseData = deserialize<UploadProfessionalImage201Response, UploadProfessionalImage201Response>(_response.data!, 'UploadProfessionalImage201Response', growable: true);
    } catch (error, stackTrace) {
      throw DioError(
        requestOptions: _response.requestOptions,
        response: _response,
        type: DioErrorType.other,
        error: error,
      )..stackTrace = stackTrace;
    }

    return Response<UploadProfessionalImage201Response>(
      data: _responseData,
      headers: _response.headers,
      isRedirect: _response.isRedirect,
      requestOptions: _response.requestOptions,
      redirects: _response.redirects,
      statusCode: _response.statusCode,
      statusMessage: _response.statusMessage,
      extra: _response.extra,
    );
  }

As you can see _bodyData is completely empty.

This is a problem because it makes this API call completely useless and swapping to standard dart generator would mean a lot of refactoring and losing features for us.

openapi-generator version

From 6.0.0 and onward

5.4.0 works fine

OpenAPI declaration file content or url
 "/images/professionals/{professionalId}/": {
            "post": {
                "security": [
                    {
                        "BearerToken": []
                    }
                ],
                "description": "Upload image for professional (profile image)",
                "consumes": [
                    "multipart/form-data"
                ],
                "tags": [
                    "Image"
                ],
                "operationId": "UploadProfessionalImage",
                "parameters": [
                    {
                        "type": "file",
                        "description": "Image file",
                        "name": "image",
                        "in": "formData",
                        "required": false
                    },
                    {
                        "type": "string",
                        "description": "Professional ID",
                        "name": "professionalId",
                        "in": "path",
                        "required": true
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Created",
                        "schema": {
                            "allOf": [
                                {
                                    "type": "object"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/definitions/dto.Image"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "default": {
                        "description": "",
                        "schema": {
                            "allOf": [
                                {
                                    "type": "object"
                                },
                                {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "$ref": "#/definitions/errs.E"
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        },
Generation Details

openapi-generator-cli generate -i swagger.json -g dart-dio -o ./ -p dateLibrary=timemachine,pubLibrary=eliva.api,pubName=project_api,serializationLibrary=json_serializable

Steps to reproduce

Just generate using the command and the faulty code appears

Suggest a fix

No idea unfortunatelly

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

Reproduce the issue with the supplied OpenAPI declaration and the openapi-generator-cli command using dart-dio, json_serializable, and timemachine. Compare the generated uploadProfessionalImage method with the working dart generator and the 5.4.0 output. Done means the generated dart-dio method includes the provided MultipartFile in the multipart request body rather than leaving _bodyData empty.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.