Skip to content

Memory Leak Due to Response Cloning #779

Open
@maiky-apex

Description

@maiky-apex

Description

We have identified a memory leak in our application that appears to be related to the swagger-typescript-api package. After thorough investigation, we traced the issue to a change introduced in this commit, which was merged on September 5, 2024.

Problem

In the commit referenced above, the response of the auto-generated customFetch function is cloned before being returned. This clone operation is causing a memory leak in our application.

Observation

Without the clone operation, the memory leak does not occur.
The memory usage increases steadily when the clone method is used, indicating a potential problem with how the response is handled.

Steps to Reproduce

Use the swagger-typescript-api package version that includes the commit ac99885.
Generate API client code using swagger-typescript-api.
Make API requests using the generated client.
Observe memory usage over time with and without the response being cloned.

Expected Behavior

The response should be returned without causing a memory leak, and the memory usage should remain stable.

Actual Behavior

The memory usage increases steadily, leading to a memory leak when the response is cloned.

Additional Context

Here's a snippet of the auto-generated code that causes the issue:

    return this.customFetch(`${baseUrl || this.baseUrl || ''}${path}${queryString ? `?${queryString}` : ''}`, {
      ...requestParams,
      headers: {
        ...(requestParams.headers || {}),
        ...(type && type !== ContentType.FormData ? { 'Content-Type': type } : {}),
      },
      signal: (cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal) || null,
      body: typeof body === 'undefined' || body === null ? null : payloadFormatter(body),
    }).then(async (response) => {
      const r = response.clone() as HttpResponse<T, E>;
      r.data = null as unknown as T;
      r.error = null as unknown as E;

      const data = !responseFormat
        ? r
        : await response[responseFormat]()
            .then((data) => {
              if (r.ok) {
                r.data = data;
              } else {
                r.error = data;
              }
              return r;
            })
            .catch((e) => {
              r.error = e;
              return r;
            });

      if (cancelToken) {
        this.abortControllers.delete(cancelToken);
      }

      if (!response.ok) throw data;
      return data;
    });
  };
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions