chenshuai2144 / openapi2typescript

一个被大范围使用的小工具
297 stars 133 forks source link

Multipart encoding not taken into account #52

Open trafreider opened 2 years ago

trafreider commented 2 years ago

Hi,

I having a Spring Boot application where I have a REST endpoint that consumes "multipart/form-data". The endpoint expects two file parts, the userData of type "application/json" and a profile picture of type image. Unfortunately, the openapi generator ignores the encoding of userData which leads to a HTTP 415 error in Spring. I would expect that the generator produces something like

formData.append('userData', new Blob([
       jsonPayload
   ], {
       type: "application/json"
   }));

Here's a snipptet of my swagger defintion.

"requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "userData"
                ],
                "type": "object",
                "properties": {
                  "userData": {
                    "$ref": "#/components/schemas/UserWithPasswordData"
                  },
                  "profilePicture": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              },
              "encoding": {
                "userData": {
                  "contentType": "application/json"
                }
              }
            }
          }
        },
chenshuai2144 commented 2 years ago

Welcome to a pr to help us deal with more boundary situations. Or provide a full JSON

trafreider commented 2 years ago

Thanks for welcoming me.

Unfortunately, I cannot create a PR due to missing permissions. Attached find a patch in my OneDrive that solves my problem https://1drv.ms/u/s!AlOH0S0Al0lig59hIbSwkJNVHXEoVA?e=AR8uQI

trafreider commented 2 years ago

The output of the generator looks as follows:

export async function updateUser(
  // 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
  params: API.updateUserParams,
  body: {
    userData: API.UserWithPasswordData;
  },
  files?: File[],
  options?: { [key: string]: any },
) {
  const { username: param0, ...queryParams } = params;
  const formData = new FormData();
  if (files) {
    formData.append('profilePicture', files[0] || '');
  }
  Object.keys(body).forEach((ele) => {
    const item = (body as any)[ele];

    if (item !== undefined && item !== null) {
      if (typeof item === 'object' && !(item instanceof File)) {
        formData.append(ele, new Blob([JSON.stringify(item)], { type: 'application/json' }));
      } else {
        formData.append(ele, item);
      }
    }
  });

  return request<API.UserResponseData>(`/api/admin/user/${param0}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'multipart/form-data',
    },
    params: { ...queryParams },
    data: formData,
    requestType: 'form',
    ...(options || {}),
  });