Skip to content

Commit

Permalink
feat: Replace JSON.NET with System.Text.Json
Browse files Browse the repository at this point in the history
  • Loading branch information
HofmeisterAn committed Nov 5, 2024
1 parent 0c69aca commit 513a3fe
Show file tree
Hide file tree
Showing 316 changed files with 1,976 additions and 2,297 deletions.
5 changes: 4 additions & 1 deletion src/Docker.DotNet/Docker.DotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
<PackageId>Docker.DotNet.Enhanced</PackageId>
<Description>Docker.DotNet is a library that allows you to interact with the Docker Remote API programmatically with fully asynchronous, non-blocking and object-oriented code in your .NET applications.</Description>
<AssemblyName>Docker.DotNet</AssemblyName>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.IO.Pipelines" Version="8.0.0" />
<PackageReference Include="System.Net.Http.Json" Version="8.0.1" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>
</Project>
77 changes: 62 additions & 15 deletions src/Docker.DotNet/DockerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ internal DockerClient(DockerClientConfiguration configuration, Version requested
Configuration = configuration;
DefaultTimeout = configuration.DefaultTimeout;

JsonSerializer = new JsonSerializer();
Images = new ImageOperations(this);
Containers = new ContainerOperations(this);
System = new SystemOperations(this);
Expand Down Expand Up @@ -149,57 +148,100 @@ await sock.ConnectAsync(new Microsoft.Net.Http.Client.UnixDomainSocketEndPoint(p

public IExecOperations Exec { get; }

internal JsonSerializer JsonSerializer { get; }
internal JsonSerializer JsonSerializer => JsonSerializer.Instance;

public void Dispose()
{
Configuration.Dispose();
_client.Dispose();
}

internal Task<DockerApiResponse> MakeRequestAsync(
internal Task MakeRequestAsync(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
CancellationToken token)
{
return MakeRequestAsync(errorHandlers, method, path, null, null, token);
return MakeRequestAsync<NoContent>(errorHandlers, method, path, null, null, token);
}

internal Task<DockerApiResponse> MakeRequestAsync(
internal Task<T> MakeRequestAsync<T>(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
CancellationToken token)
{
return MakeRequestAsync<T>(errorHandlers, method, path, null, null, token);
}

internal Task MakeRequestAsync(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
IQueryString queryString,
CancellationToken token)
{
return MakeRequestAsync<NoContent>(errorHandlers, method, path, queryString, null, token);
}

internal Task<T> MakeRequestAsync<T>(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
IQueryString queryString,
CancellationToken token)
{
return MakeRequestAsync<T>(errorHandlers, method, path, queryString, null, token);
}

internal Task MakeRequestAsync(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
IQueryString queryString,
IRequestContent body,
CancellationToken token)
{
return MakeRequestAsync<NoContent>(errorHandlers, method, path, queryString, body, null, token);
}

internal Task<T> MakeRequestAsync<T>(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
IQueryString queryString,
IRequestContent body,
CancellationToken token)
{
return MakeRequestAsync(errorHandlers, method, path, queryString, null, token);
return MakeRequestAsync<T>(errorHandlers, method, path, queryString, body, null, token);
}

internal Task<DockerApiResponse> MakeRequestAsync(
internal Task<T> MakeRequestAsync<T>(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
IQueryString queryString,
IRequestContent body,
IDictionary<string, string> headers,
CancellationToken token)
{
return MakeRequestAsync(errorHandlers, method, path, queryString, body, null, token);
return MakeRequestAsync<T>(errorHandlers, method, path, queryString, body, headers, DefaultTimeout, token);
}

internal Task<DockerApiResponse> MakeRequestAsync(
internal Task MakeRequestAsync(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
IQueryString queryString,
IRequestContent body,
IDictionary<string, string> headers,
TimeSpan timeout,
CancellationToken token)
{
return MakeRequestAsync(errorHandlers, method, path, queryString, body, headers, DefaultTimeout, token);
return MakeRequestAsync<NoContent>(errorHandlers, method, path, queryString, body, headers, timeout, token);
}

internal async Task<DockerApiResponse> MakeRequestAsync(
internal async Task<T> MakeRequestAsync<T>(
IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers,
HttpMethod method,
string path,
Expand All @@ -217,10 +259,13 @@ internal async Task<DockerApiResponse> MakeRequestAsync(
await HandleIfErrorResponseAsync(response.StatusCode, response, errorHandlers)
.ConfigureAwait(false);

var responseBody = await response.Content.ReadAsStringAsync()
.ConfigureAwait(false);
if (typeof(T) == typeof(NoContent))
{
return default;
}

return new DockerApiResponse(response.StatusCode, responseBody);
return await JsonSerializer.DeserializeAsync<T>(response.Content, token)
.ConfigureAwait(false);
}
}

Expand Down Expand Up @@ -294,7 +339,7 @@ internal async Task<HttpResponseMessage> MakeRequestForRawResponseAsync(
IDictionary<string, string> headers,
CancellationToken token)
{
var response = await PrivateMakeRequestAsync(SInfiniteTimeout, HttpCompletionOption.ResponseHeadersRead, method, path, queryString, headers, body, token).ConfigureAwait(false);
var response = await PrivateMakeRequestAsync(SInfiniteTimeout, HttpCompletionOption.ResponseHeadersRead, method, path, queryString, headers, body, token).ConfigureAwait(false);
await HandleIfErrorResponseAsync(response.StatusCode, response)
.ConfigureAwait(false);
return response;
Expand Down Expand Up @@ -469,6 +514,8 @@ private async Task HandleIfErrorResponseAsync(HttpStatusCode statusCode, HttpRes
throw new DockerApiException(statusCode, responseBody);
}
}

private struct NoContent {}
}

internal delegate void ApiResponseErrorHandlingDelegate(HttpStatusCode statusCode, string responseBody);
Expand Down
11 changes: 4 additions & 7 deletions src/Docker.DotNet/Endpoints/ConfigsOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ internal ConfigOperations(DockerClient client)

async Task<IList<SwarmConfig>> IConfigOperations.ListConfigsAsync(CancellationToken cancellationToken)
{
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<IList<SwarmConfig>>(response.Body);
return await _client.MakeRequestAsync<IList<SwarmConfig>>(_client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken).ConfigureAwait(false);
}

async Task<SwarmCreateConfigResponse> IConfigOperations.CreateConfigAsync(SwarmCreateConfigParameters body, CancellationToken cancellationToken)
Expand All @@ -30,8 +29,7 @@ async Task<SwarmCreateConfigResponse> IConfigOperations.CreateConfigAsync(SwarmC
}

var data = new JsonRequestContent<SwarmConfigSpec>(body.Config, _client.JsonSerializer);
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Post, "configs/create", null, data, cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<SwarmCreateConfigResponse>(response.Body);
return await _client.MakeRequestAsync<SwarmCreateConfigResponse>(_client.NoErrorHandlers, HttpMethod.Post, "configs/create", null, data, cancellationToken).ConfigureAwait(false);
}

async Task<SwarmConfig> IConfigOperations.InspectConfigAsync(string id, CancellationToken cancellationToken)
Expand All @@ -41,8 +39,7 @@ async Task<SwarmConfig> IConfigOperations.InspectConfigAsync(string id, Cancella
throw new ArgumentNullException(nameof(id));
}

var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Get, $"configs/{id}", cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<SwarmConfig>(response.Body);
return await _client.MakeRequestAsync<SwarmConfig>(_client.NoErrorHandlers, HttpMethod.Get, $"configs/{id}", cancellationToken).ConfigureAwait(false);
}

Task IConfigOperations.RemoveConfigAsync(string id, CancellationToken cancellationToken)
Expand All @@ -55,4 +52,4 @@ Task IConfigOperations.RemoveConfigAsync(string id, CancellationToken cancellati
return _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Delete, $"configs/{id}", cancellationToken);
}
}
}
}
39 changes: 15 additions & 24 deletions src/Docker.DotNet/Endpoints/ContainerOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -43,8 +42,7 @@ internal ContainerOperations(DockerClient client)
}

IQueryString queryParameters = new QueryString<ContainersListParameters>(parameters);
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Get, "containers/json", queryParameters, cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<ContainerListResponse[]>(response.Body);
return await _client.MakeRequestAsync<ContainerListResponse[]>(_client.NoErrorHandlers, HttpMethod.Get, "containers/json", queryParameters, cancellationToken).ConfigureAwait(false);
}

public async Task<CreateContainerResponse> CreateContainerAsync(CreateContainerParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -62,8 +60,7 @@ internal ContainerOperations(DockerClient client)
}

var data = new JsonRequestContent<CreateContainerParameters>(parameters, _client.JsonSerializer);
var response = await _client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Post, "containers/create", qs, data, cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<CreateContainerResponse>(response.Body);
return await _client.MakeRequestAsync<CreateContainerResponse>(new[] { NoSuchImageHandler }, HttpMethod.Post, "containers/create", qs, data, cancellationToken).ConfigureAwait(false);
}

public async Task<ContainerInspectResponse> InspectContainerAsync(string id, CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -73,8 +70,7 @@ internal ContainerOperations(DockerClient client)
throw new ArgumentNullException(nameof(id));
}

var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/json", cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<ContainerInspectResponse>(response.Body);
return await _client.MakeRequestAsync<ContainerInspectResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/json", cancellationToken).ConfigureAwait(false);
}

public async Task<ContainerProcessesResponse> ListProcessesAsync(string id, ContainerListProcessesParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -90,8 +86,7 @@ internal ContainerOperations(DockerClient client)
}

IQueryString queryParameters = new QueryString<ContainerListProcessesParameters>(parameters);
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/top", queryParameters, cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<ContainerProcessesResponse>(response.Body);
return await _client.MakeRequestAsync<ContainerProcessesResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/top", queryParameters, cancellationToken).ConfigureAwait(false);
}

public Task<Stream> GetContainerLogsAsync(string id, ContainerLogsParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
Expand Down Expand Up @@ -145,8 +140,7 @@ public Task GetContainerLogsAsync(string id, ContainerLogsParameters parameters,
throw new ArgumentNullException(nameof(id));
}

var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/changes", cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<ContainerFileSystemChangeResponse[]>(response.Body);
return await _client.MakeRequestAsync<ContainerFileSystemChangeResponse[]>(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/changes", cancellationToken).ConfigureAwait(false);
}

public Task<Stream> ExportContainerAsync(string id, CancellationToken cancellationToken)
Expand Down Expand Up @@ -208,8 +202,9 @@ public Task<Stream> GetContainerStatsAsync(string id, ContainerStatsParameters p
}

var queryParams = parameters == null ? null : new QueryString<ContainerStartParameters>(parameters);
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/start", queryParams, cancellationToken).ConfigureAwait(false);
return response.StatusCode != HttpStatusCode.NotModified;
bool? result = null;
await _client.MakeRequestAsync(new[] { NoSuchContainerHandler, (statusCode, _) => result = statusCode != HttpStatusCode.NotModified }, HttpMethod.Post, $"containers/{id}/start", queryParams, cancellationToken).ConfigureAwait(false);
return result ?? throw new InvalidOperationException();
}

public async Task<bool> StopContainerAsync(string id, ContainerStopParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -227,8 +222,9 @@ public Task<Stream> GetContainerStatsAsync(string id, ContainerStatsParameters p
IQueryString queryParameters = new QueryString<ContainerStopParameters>(parameters);
// since specified wait timespan can be greater than HttpClient's default, we set the
// client timeout to infinite and provide a cancellation token.
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/stop", queryParameters, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
return response.StatusCode != HttpStatusCode.NotModified;
bool? result = null;
await _client.MakeRequestAsync(new[] { NoSuchContainerHandler, (statusCode, _) => result = statusCode != HttpStatusCode.NotModified }, HttpMethod.Post, $"containers/{id}/stop", queryParameters, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
return result ?? throw new InvalidOperationException();
}

public Task RestartContainerAsync(string id, ContainerRestartParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
Expand Down Expand Up @@ -327,8 +323,7 @@ public Task RenameContainerAsync(string id, ContainerRenameParameters parameters
throw new ArgumentNullException(nameof(id));
}

var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/wait", null, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<ContainerWaitResponse>(response.Body);
return await _client.MakeRequestAsync<ContainerWaitResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/wait", null, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false);
}

public Task RemoveContainerAsync(string id, ContainerRemoveParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
Expand Down Expand Up @@ -367,9 +362,7 @@ public Task RenameContainerAsync(string id, ContainerRenameParameters parameters

var bytes = Convert.FromBase64String(statHeader);

var stat = Encoding.UTF8.GetString(bytes, 0, bytes.Length);

var pathStat = _client.JsonSerializer.DeserializeObject<ContainerPathStatResponse>(stat);
var pathStat = _client.JsonSerializer.Deserialize<ContainerPathStatResponse>(bytes);

return new GetArchiveFromContainerResponse
{
Expand Down Expand Up @@ -399,8 +392,7 @@ public Task RenameContainerAsync(string id, ContainerRenameParameters parameters
public async Task<ContainersPruneResponse> PruneContainersAsync(ContainersPruneParameters parameters, CancellationToken cancellationToken)
{
var queryParameters = parameters == null ? null : new QueryString<ContainersPruneParameters>(parameters);
var response = await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Post, "containers/prune", queryParameters, cancellationToken).ConfigureAwait(false);
return _client.JsonSerializer.DeserializeObject<ContainersPruneResponse>(response.Body);
return await _client.MakeRequestAsync<ContainersPruneResponse>(_client.NoErrorHandlers, HttpMethod.Post, "containers/prune", queryParameters, cancellationToken).ConfigureAwait(false);
}

public async Task<ContainerUpdateResponse> UpdateContainerAsync(string id, ContainerUpdateParameters parameters, CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -416,8 +408,7 @@ public async Task<ContainersPruneResponse> PruneContainersAsync(ContainersPruneP
}

var data = new JsonRequestContent<ContainerUpdateParameters>(parameters, _client.JsonSerializer);
var response = await _client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/update", null, data, cancellationToken);
return _client.JsonSerializer.DeserializeObject<ContainerUpdateResponse>(response.Body);
return await _client.MakeRequestAsync<ContainerUpdateResponse>(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/update", null, data, cancellationToken);
}
}
}
Loading

0 comments on commit 513a3fe

Please sign in to comment.