[BUG] [csharp-netcore] Memory leak in ApiClient
Created by: aarseneau-idexx
Bug Report Checklist
-
Have you provided a full/minimal spec to reproduce the issue? - [N/A] 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? - [N/A ] What's the actual output vs expected output?
-
[Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
In csharp-netcore, using RestClient as the "library" option (this is the default), the ApiClient class create an instance of a RestClient for each call to Exec() and ExecAsync(). RestClient implements the IDisposable interface because they create a HttpClient when constructed. The HttpClient also implements IDisposable and must be called to free it's resources.
Both Exec() and ExecAsync() do not directly or indirectly dispose of the RestClient . Each time a HTTP request is made using the auto-generated client, a HttpClient is leaked.
openapi-generator version
v6.2.1
OpenAPI declaration file content or url
N/A
Generation Details
N/A
Steps to reproduce
Create a client using the csharp-dotnet generator, leaving the "library" option set to default (i.e. RestClient). Instantiate the client. In a loop make 100 requests using the client. Set a break point after the loop Debug the program. At the breakpoint, investigate the memory and you will see 100 HttpClient objects in memory.
Related issues/PRs
Could not find a related issue.
Suggest a fix
Reference to mustache file that generates the Client: https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/csharp-netcore/ApiClient.mustache
For C# 8.0 and up, you could add "using" on the same line that the RestClient is created for both Exec and ExecAsync. If you need to support older versions of C#, you could wrap the entire usage of the rest client in
using (RestClient RestClient client = new RestClient(clientOptions)
.UseSerializer(() => new CustomJsonCodec(SerializerSettings, configuration)))
{
// The rest of the Exec<T>/ExecAsync<T> method body
}