From 6a87013e18ed0f02c9e296a53f1707e538e4780c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Thu, 7 Mar 2024 17:53:33 +0100 Subject: [PATCH] Avoid roundtrip to string by deserializing directly from the HTTP response stream --- src/Docker.DotNet/DockerApiResponse.cs | 17 ----- src/Docker.DotNet/DockerClient.cs | 73 ++++++++++++++++--- .../Endpoints/ConfigsOperations.cs | 9 +-- .../Endpoints/ContainerOperations.cs | 39 ++++------ src/Docker.DotNet/Endpoints/ExecOperations.cs | 6 +- .../Endpoints/ImageOperations.cs | 21 ++---- .../Endpoints/NetworkOperations.cs | 12 +-- .../Endpoints/PluginOperations.cs | 9 +-- .../Endpoints/SecretsOperations.cs | 9 +-- .../Endpoints/SwarmOperations.cs | 30 +++----- .../Endpoints/SystemOperations.cs | 12 ++- .../Endpoints/TasksOperations.cs | 6 +- .../Endpoints/VolumeOperations.cs | 16 ++-- src/Docker.DotNet/JsonSerializer.cs | 10 ++- 14 files changed, 129 insertions(+), 140 deletions(-) delete mode 100644 src/Docker.DotNet/DockerApiResponse.cs diff --git a/src/Docker.DotNet/DockerApiResponse.cs b/src/Docker.DotNet/DockerApiResponse.cs deleted file mode 100644 index 8639137d4..000000000 --- a/src/Docker.DotNet/DockerApiResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Net; - -namespace Docker.DotNet -{ - internal class DockerApiResponse - { - public HttpStatusCode StatusCode { get; private set; } - - public string Body { get; private set; } - - public DockerApiResponse(HttpStatusCode statusCode, string body) - { - this.StatusCode = statusCode; - this.Body = body; - } - } -} \ No newline at end of file diff --git a/src/Docker.DotNet/DockerClient.cs b/src/Docker.DotNet/DockerClient.cs index 64a428f84..f04e24eec 100644 --- a/src/Docker.DotNet/DockerClient.cs +++ b/src/Docker.DotNet/DockerClient.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; @@ -157,49 +158,92 @@ public void Dispose() _client.Dispose(); } - internal Task MakeRequestAsync( + internal Task MakeRequestAsync( IEnumerable errorHandlers, HttpMethod method, string path, CancellationToken token) { - return MakeRequestAsync(errorHandlers, method, path, null, null, token); + return MakeRequestAsync(errorHandlers, method, path, null, null, token); } - internal Task MakeRequestAsync( + internal Task MakeRequestAsync( + IEnumerable errorHandlers, + HttpMethod method, + string path, + CancellationToken token) + { + return MakeRequestAsync(errorHandlers, method, path, null, null, token); + } + + internal Task MakeRequestAsync( + IEnumerable errorHandlers, + HttpMethod method, + string path, + IQueryString queryString, + CancellationToken token) + { + return MakeRequestAsync(errorHandlers, method, path, queryString, null, token); + } + + internal Task MakeRequestAsync( + IEnumerable errorHandlers, + HttpMethod method, + string path, + IQueryString queryString, + CancellationToken token) + { + return MakeRequestAsync(errorHandlers, method, path, queryString, null, token); + } + + internal Task MakeRequestAsync( + IEnumerable errorHandlers, + HttpMethod method, + string path, + IQueryString queryString, + IRequestContent body, + CancellationToken token) + { + return MakeRequestAsync(errorHandlers, method, path, queryString, body, null, token); + } + + internal Task MakeRequestAsync( IEnumerable errorHandlers, HttpMethod method, string path, IQueryString queryString, + IRequestContent body, CancellationToken token) { - return MakeRequestAsync(errorHandlers, method, path, queryString, null, token); + return MakeRequestAsync(errorHandlers, method, path, queryString, body, null, token); } - internal Task MakeRequestAsync( + internal Task MakeRequestAsync( IEnumerable errorHandlers, HttpMethod method, string path, IQueryString queryString, IRequestContent body, + IDictionary headers, CancellationToken token) { - return MakeRequestAsync(errorHandlers, method, path, queryString, body, null, token); + return MakeRequestAsync(errorHandlers, method, path, queryString, body, headers, DefaultTimeout, token); } - internal Task MakeRequestAsync( + internal Task MakeRequestAsync( IEnumerable errorHandlers, HttpMethod method, string path, IQueryString queryString, IRequestContent body, IDictionary headers, + TimeSpan timeout, CancellationToken token) { - return MakeRequestAsync(errorHandlers, method, path, queryString, body, headers, DefaultTimeout, token); + return MakeRequestAsync(errorHandlers, method, path, queryString, body, headers, timeout, token); } - internal async Task MakeRequestAsync( + internal async Task MakeRequestAsync( IEnumerable errorHandlers, HttpMethod method, string path, @@ -217,10 +261,13 @@ internal async Task 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(response.Content, token) + .ConfigureAwait(false); } } @@ -469,6 +516,8 @@ private async Task HandleIfErrorResponseAsync(HttpStatusCode statusCode, HttpRes throw new DockerApiException(statusCode, responseBody); } } + + private struct NoContent {} } internal delegate void ApiResponseErrorHandlingDelegate(HttpStatusCode statusCode, string responseBody); diff --git a/src/Docker.DotNet/Endpoints/ConfigsOperations.cs b/src/Docker.DotNet/Endpoints/ConfigsOperations.cs index ec1182634..ac466c294 100644 --- a/src/Docker.DotNet/Endpoints/ConfigsOperations.cs +++ b/src/Docker.DotNet/Endpoints/ConfigsOperations.cs @@ -18,8 +18,7 @@ internal ConfigOperations(DockerClient client) async Task> IConfigOperations.ListConfigsAsync(CancellationToken cancellationToken) { - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject>(response.Body); + return await this._client.MakeRequestAsync>(this._client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken).ConfigureAwait(false); } async Task IConfigOperations.CreateConfigAsync(SwarmCreateConfigParameters body, CancellationToken cancellationToken) @@ -30,8 +29,7 @@ async Task IConfigOperations.CreateConfigAsync(SwarmC } var data = new JsonRequestContent(body.Config, this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "configs/create", null, data, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "configs/create", null, data, cancellationToken).ConfigureAwait(false); } async Task IConfigOperations.InspectConfigAsync(string id, CancellationToken cancellationToken) @@ -41,8 +39,7 @@ async Task IConfigOperations.InspectConfigAsync(string id, Cancella throw new ArgumentNullException(nameof(id)); } - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"configs/{id}", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"configs/{id}", cancellationToken).ConfigureAwait(false); } Task IConfigOperations.RemoveConfigAsync(string id, CancellationToken cancellationToken) diff --git a/src/Docker.DotNet/Endpoints/ContainerOperations.cs b/src/Docker.DotNet/Endpoints/ContainerOperations.cs index 4fd1e3431..7db06f3c3 100644 --- a/src/Docker.DotNet/Endpoints/ContainerOperations.cs +++ b/src/Docker.DotNet/Endpoints/ContainerOperations.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Net; using System.Net.Http; -using System.Text; using System.Threading; using System.Threading.Tasks; @@ -43,8 +42,7 @@ internal ContainerOperations(DockerClient client) } IQueryString queryParameters = new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "containers/json", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "containers/json", queryParameters, cancellationToken).ConfigureAwait(false); } public async Task CreateContainerAsync(CreateContainerParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -62,8 +60,7 @@ internal ContainerOperations(DockerClient client) } var data = new JsonRequestContent(parameters, this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Post, "containers/create", qs, data, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Post, "containers/create", qs, data, cancellationToken).ConfigureAwait(false); } public async Task InspectContainerAsync(string id, CancellationToken cancellationToken = default(CancellationToken)) @@ -73,8 +70,7 @@ internal ContainerOperations(DockerClient client) throw new ArgumentNullException(nameof(id)); } - var response = await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/json", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/json", cancellationToken).ConfigureAwait(false); } public async Task ListProcessesAsync(string id, ContainerListProcessesParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -90,8 +86,7 @@ internal ContainerOperations(DockerClient client) } IQueryString queryParameters = new QueryString(parameters); - var response = await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/top", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/top", queryParameters, cancellationToken).ConfigureAwait(false); } public Task GetContainerLogsAsync(string id, ContainerLogsParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -145,8 +140,7 @@ public Task GetContainerLogsAsync(string id, ContainerLogsParameters parameters, throw new ArgumentNullException(nameof(id)); } - var response = await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/changes", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"containers/{id}/changes", cancellationToken).ConfigureAwait(false); } public Task ExportContainerAsync(string id, CancellationToken cancellationToken) @@ -208,8 +202,9 @@ public Task GetContainerStatsAsync(string id, ContainerStatsParameters p } var queryParams = parameters == null ? null : new QueryString(parameters); - var response = await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/start", queryParams, cancellationToken).ConfigureAwait(false); - return response.StatusCode != HttpStatusCode.NotModified; + bool? result = null; + await this._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 StopContainerAsync(string id, ContainerStopParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -227,8 +222,9 @@ public Task GetContainerStatsAsync(string id, ContainerStatsParameters p IQueryString queryParameters = new QueryString(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 this._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 this._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)) @@ -327,8 +323,7 @@ public Task RenameContainerAsync(string id, ContainerRenameParameters parameters throw new ArgumentNullException(nameof(id)); } - var response = await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/wait", null, null, null, TimeSpan.FromMilliseconds(Timeout.Infinite), cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(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)) @@ -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 = this._client.JsonSerializer.DeserializeObject(stat); + var pathStat = this._client.JsonSerializer.DeserializeObject(bytes); return new GetArchiveFromContainerResponse { @@ -399,8 +392,7 @@ public Task RenameContainerAsync(string id, ContainerRenameParameters parameters public async Task PruneContainersAsync(ContainersPruneParameters parameters, CancellationToken cancellationToken) { var queryParameters = parameters == null ? null : new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "containers/prune", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "containers/prune", queryParameters, cancellationToken).ConfigureAwait(false); } public async Task UpdateContainerAsync(string id, ContainerUpdateParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -416,8 +408,7 @@ public async Task PruneContainersAsync(ContainersPruneP } var data = new JsonRequestContent(parameters, this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/update", null, data, cancellationToken); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/update", null, data, cancellationToken); } } } \ No newline at end of file diff --git a/src/Docker.DotNet/Endpoints/ExecOperations.cs b/src/Docker.DotNet/Endpoints/ExecOperations.cs index 5b0152f60..0930eab3b 100644 --- a/src/Docker.DotNet/Endpoints/ExecOperations.cs +++ b/src/Docker.DotNet/Endpoints/ExecOperations.cs @@ -37,8 +37,7 @@ internal ExecOperations(DockerClient client) } var data = new JsonRequestContent(parameters, this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/exec", null, data, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Post, $"containers/{id}/exec", null, data, cancellationToken).ConfigureAwait(false); } public async Task InspectContainerExecAsync(string id, CancellationToken cancellationToken) @@ -48,8 +47,7 @@ public async Task InspectContainerExecAsync(string throw new ArgumentNullException(nameof(id)); } - var response = await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"exec/{id}/json", null, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchContainerHandler }, HttpMethod.Get, $"exec/{id}/json", null, cancellationToken).ConfigureAwait(false); } public Task ResizeContainerExecTtyAsync(string id, ContainerResizeParameters parameters, CancellationToken cancellationToken) diff --git a/src/Docker.DotNet/Endpoints/ImageOperations.cs b/src/Docker.DotNet/Endpoints/ImageOperations.cs index 6360da4bf..39d249ea0 100644 --- a/src/Docker.DotNet/Endpoints/ImageOperations.cs +++ b/src/Docker.DotNet/Endpoints/ImageOperations.cs @@ -40,8 +40,7 @@ internal ImageOperations(DockerClient client) } IQueryString queryParameters = new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "images/json", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "images/json", queryParameters, cancellationToken).ConfigureAwait(false); } public Task BuildImageFromDockerfileAsync(Stream contents, ImageBuildParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -160,8 +159,7 @@ public Task BuildImageFromDockerfileAsync(ImageBuildParameters parameters, Strea throw new ArgumentNullException(nameof(name)); } - var response = await this._client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Get, $"images/{name}/json", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Get, $"images/{name}/json", cancellationToken).ConfigureAwait(false); } public async Task> GetImageHistoryAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) @@ -171,8 +169,7 @@ public Task BuildImageFromDockerfileAsync(ImageBuildParameters parameters, Strea throw new ArgumentNullException(nameof(name)); } - var response = await this._client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Get, $"images/{name}/history", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Get, $"images/{name}/history", cancellationToken).ConfigureAwait(false); } public Task PushImageAsync(string name, ImagePushParameters parameters, AuthConfig authConfig, IProgress progress, CancellationToken cancellationToken = default(CancellationToken)) @@ -224,8 +221,7 @@ public Task BuildImageFromDockerfileAsync(ImageBuildParameters parameters, Strea } IQueryString queryParameters = new QueryString(parameters); - var response = await this._client.MakeRequestAsync(new[] { NoSuchImageHandler }, HttpMethod.Delete, $"images/{name}", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject[]>(response.Body); + return await this._client.MakeRequestAsync[]>(new[] { NoSuchImageHandler }, HttpMethod.Delete, $"images/{name}", queryParameters, cancellationToken).ConfigureAwait(false); } public async Task> SearchImagesAsync(ImagesSearchParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -236,15 +232,13 @@ public Task BuildImageFromDockerfileAsync(ImageBuildParameters parameters, Strea } IQueryString queryParameters = new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "images/search", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "images/search", queryParameters, cancellationToken).ConfigureAwait(false); } public async Task PruneImagesAsync(ImagesPruneParameters parameters, CancellationToken cancellationToken) { var queryParameters = parameters == null ? null : new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "images/prune", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "images/prune", queryParameters, cancellationToken).ConfigureAwait(false); } public async Task CommitContainerChangesAsync(CommitContainerChangesParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -257,8 +251,7 @@ public async Task PruneImagesAsync(ImagesPruneParameters pa var data = new JsonRequestContent(parameters, this._client.JsonSerializer); IQueryString queryParameters = new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "commit", queryParameters, data, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "commit", queryParameters, data, cancellationToken).ConfigureAwait(false); } public Task SaveImageAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/src/Docker.DotNet/Endpoints/NetworkOperations.cs b/src/Docker.DotNet/Endpoints/NetworkOperations.cs index a4757b82f..f8febe0de 100644 --- a/src/Docker.DotNet/Endpoints/NetworkOperations.cs +++ b/src/Docker.DotNet/Endpoints/NetworkOperations.cs @@ -29,8 +29,7 @@ internal NetworkOperations(DockerClient client) async Task> INetworkOperations.ListNetworksAsync(NetworksListParameters parameters, CancellationToken cancellationToken) { var queryParameters = parameters == null ? null : new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "networks", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "networks", queryParameters, cancellationToken).ConfigureAwait(false); } async Task INetworkOperations.InspectNetworkAsync(string id, CancellationToken cancellationToken) @@ -40,8 +39,7 @@ async Task INetworkOperations.InspectNetworkAsync(string id, Ca throw new ArgumentNullException(nameof(id)); } - var response = await this._client.MakeRequestAsync(new[] { NoSuchNetworkHandler }, HttpMethod.Get, $"networks/{id}", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchNetworkHandler }, HttpMethod.Get, $"networks/{id}", cancellationToken).ConfigureAwait(false); } Task INetworkOperations.DeleteNetworkAsync(string id, CancellationToken cancellationToken) @@ -62,8 +60,7 @@ async Task INetworkOperations.CreateNetworkAsync(Network } var data = new JsonRequestContent(parameters, this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "networks/create", null, data, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "networks/create", null, data, cancellationToken).ConfigureAwait(false); } Task INetworkOperations.ConnectNetworkAsync(string id, NetworkConnectParameters parameters, CancellationToken cancellationToken) @@ -106,8 +103,7 @@ Task INetworkOperations.DeleteUnusedNetworksAsync(NetworksDeleteUnusedParameters async Task INetworkOperations.PruneNetworksAsync(NetworksDeleteUnusedParameters parameters, CancellationToken cancellationToken) { var queryParameters = parameters == null ? null : new QueryString(parameters); - var response = await this._client.MakeRequestAsync(null, HttpMethod.Post, "networks/prune", queryParameters, cancellationToken); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(null, HttpMethod.Post, "networks/prune", queryParameters, cancellationToken); } } } diff --git a/src/Docker.DotNet/Endpoints/PluginOperations.cs b/src/Docker.DotNet/Endpoints/PluginOperations.cs index df6e65bbd..e26205ddc 100644 --- a/src/Docker.DotNet/Endpoints/PluginOperations.cs +++ b/src/Docker.DotNet/Endpoints/PluginOperations.cs @@ -30,8 +30,7 @@ internal PluginOperations(DockerClient client) public async Task> ListPluginsAsync(PluginListParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) { IQueryString queryParameters = parameters == null ? null : new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "plugins", queryParameters, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "plugins", queryParameters, cancellationToken).ConfigureAwait(false); } public async Task> GetPluginPrivilegesAsync(PluginGetPrivilegeParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -42,8 +41,7 @@ internal PluginOperations(DockerClient client) } var query = new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "plugins/privileges", query, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "plugins/privileges", query, cancellationToken).ConfigureAwait(false); } public Task InstallPluginAsync(PluginInstallParameters parameters, IProgress progress, CancellationToken cancellationToken = default(CancellationToken)) @@ -75,8 +73,7 @@ public async Task InspectPluginAsync(string name, CancellationToken canc throw new ArgumentNullException(nameof(name)); } - var response = await this._client.MakeRequestAsync(new[] { NoSuchPluginHandler }, HttpMethod.Get, $"plugins/{name}/json", cancellationToken); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { NoSuchPluginHandler }, HttpMethod.Get, $"plugins/{name}/json", cancellationToken); } public Task RemovePluginAsync(string name, PluginRemoveParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/src/Docker.DotNet/Endpoints/SecretsOperations.cs b/src/Docker.DotNet/Endpoints/SecretsOperations.cs index 45ea29cd1..174823c21 100644 --- a/src/Docker.DotNet/Endpoints/SecretsOperations.cs +++ b/src/Docker.DotNet/Endpoints/SecretsOperations.cs @@ -18,8 +18,7 @@ internal SecretsOperations(DockerClient client) async Task> ISecretsOperations.ListAsync(CancellationToken cancellationToken) { - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "secrets", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject>(response.Body); + return await this._client.MakeRequestAsync>(this._client.NoErrorHandlers, HttpMethod.Get, "secrets", cancellationToken).ConfigureAwait(false); } async Task ISecretsOperations.CreateAsync(SecretSpec body, CancellationToken cancellationToken) @@ -30,8 +29,7 @@ async Task ISecretsOperations.CreateAsync(SecretSpec body, } var data = new JsonRequestContent(body, this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "secrets/create", null, data, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "secrets/create", null, data, cancellationToken).ConfigureAwait(false); } async Task ISecretsOperations.InspectAsync(string id, CancellationToken cancellationToken) @@ -41,8 +39,7 @@ async Task ISecretsOperations.InspectAsync(string id, CancellationToken throw new ArgumentNullException(nameof(id)); } - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"secrets/{id}", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"secrets/{id}", cancellationToken).ConfigureAwait(false); } Task ISecretsOperations.DeleteAsync(string id, CancellationToken cancellationToken) diff --git a/src/Docker.DotNet/Endpoints/SwarmOperations.cs b/src/Docker.DotNet/Endpoints/SwarmOperations.cs index 606358704..bfbd0ec29 100644 --- a/src/Docker.DotNet/Endpoints/SwarmOperations.cs +++ b/src/Docker.DotNet/Endpoints/SwarmOperations.cs @@ -32,20 +32,18 @@ async Task ISwarmOperations.CreateServiceAsync(ServiceCre if (parameters == null) throw new ArgumentNullException(nameof(parameters)); var data = new JsonRequestContent(parameters.Service ?? throw new ArgumentNullException(nameof(parameters.Service)), this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Post, "services/create", null, data, RegistryAuthHeaders(parameters.RegistryAuth), cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Post, "services/create", null, data, RegistryAuthHeaders(parameters.RegistryAuth), cancellationToken).ConfigureAwait(false); } async Task ISwarmOperations.GetSwarmUnlockKeyAsync(CancellationToken cancellationToken) { - var response = await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, "swarm/unlockkey", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, "swarm/unlockkey", cancellationToken).ConfigureAwait(false); } async Task ISwarmOperations.InitSwarmAsync(SwarmInitParameters parameters, CancellationToken cancellationToken) { var data = new JsonRequestContent(parameters ?? throw new ArgumentNullException(nameof(parameters)), this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync( + return await this._client.MakeRequestAsync( new ApiResponseErrorHandlingDelegate[] { (statusCode, responseBody) => @@ -62,22 +60,18 @@ async Task ISwarmOperations.InitSwarmAsync(SwarmInitParameters parameter null, data, cancellationToken).ConfigureAwait(false); - - return response.Body; } async Task ISwarmOperations.InspectServiceAsync(string id, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(id)) throw new ArgumentNullException(nameof(id)); - var response = await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, $"services/{id}", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, $"services/{id}", cancellationToken).ConfigureAwait(false); } async Task ISwarmOperations.InspectSwarmAsync(CancellationToken cancellationToken) { - var response = await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, "swarm", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, "swarm", cancellationToken).ConfigureAwait(false); } async Task ISwarmOperations.JoinSwarmAsync(SwarmJoinParameters parameters, CancellationToken cancellationToken) @@ -126,10 +120,9 @@ await this._client.MakeRequestAsync( async Task> ISwarmOperations.ListServicesAsync(ServicesListParameters parameters, CancellationToken cancellationToken) { var queryParameters = parameters != null ? new QueryString(parameters) : null; - var response = await this._client - .MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, $"services", queryParameters, cancellationToken) + return await this._client + .MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, $"services", queryParameters, cancellationToken) .ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); } async Task ISwarmOperations.RemoveServiceAsync(string id, CancellationToken cancellationToken) @@ -152,8 +145,7 @@ async Task ISwarmOperations.UpdateServiceAsync(string id, var query = new QueryString(parameters); var body = new JsonRequestContent(parameters.Service ?? throw new ArgumentNullException(nameof(parameters.Service)), this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Post, $"services/{id}/update", query, body, RegistryAuthHeaders(parameters.RegistryAuth), cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Post, $"services/{id}/update", query, body, RegistryAuthHeaders(parameters.RegistryAuth), cancellationToken).ConfigureAwait(false); } public Task GetServiceLogsAsync(string id, ServiceLogsParameters parameters, CancellationToken cancellationToken = default(CancellationToken)) @@ -232,15 +224,13 @@ private IDictionary RegistryAuthHeaders(AuthConfig authConfig) async Task> ISwarmOperations.ListNodesAsync(CancellationToken cancellationToken) { - var response = await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, $"nodes", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, $"nodes", cancellationToken).ConfigureAwait(false); } async Task ISwarmOperations.InspectNodeAsync(string id, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(id)) throw new ArgumentNullException(nameof(id)); - var response = await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, $"nodes/{id}", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(new[] { SwarmResponseHandler }, HttpMethod.Get, $"nodes/{id}", cancellationToken).ConfigureAwait(false); } async Task ISwarmOperations.RemoveNodeAsync(string id, bool force, CancellationToken cancellationToken) diff --git a/src/Docker.DotNet/Endpoints/SystemOperations.cs b/src/Docker.DotNet/Endpoints/SystemOperations.cs index 50179bf0e..93d272f23 100644 --- a/src/Docker.DotNet/Endpoints/SystemOperations.cs +++ b/src/Docker.DotNet/Endpoints/SystemOperations.cs @@ -29,8 +29,7 @@ internal SystemOperations(DockerClient client) public async Task GetVersionAsync(CancellationToken cancellationToken = default(CancellationToken)) { - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "version", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "version", cancellationToken).ConfigureAwait(false); } public Task PingAsync(CancellationToken cancellationToken = default(CancellationToken)) @@ -40,8 +39,7 @@ internal SystemOperations(DockerClient client) public async Task GetSystemInfoAsync(CancellationToken cancellationToken = default(CancellationToken)) { - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "info", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "info", cancellationToken).ConfigureAwait(false); } public Task MonitorEventsAsync(ContainerEventsParameters parameters, CancellationToken cancellationToken) @@ -57,9 +55,9 @@ public Task MonitorEventsAsync(ContainerEventsParameters parameters, Can public Task MonitorEventsAsync(ContainerEventsParameters parameters, IProgress progress, CancellationToken cancellationToken = default(CancellationToken)) { - if (progress == null) - { - throw new ArgumentNullException(nameof(progress)); + if (progress == null) + { + throw new ArgumentNullException(nameof(progress)); } return StreamUtil.MonitorStreamForMessagesAsync( diff --git a/src/Docker.DotNet/Endpoints/TasksOperations.cs b/src/Docker.DotNet/Endpoints/TasksOperations.cs index d6d6d18aa..5bab20ccd 100644 --- a/src/Docker.DotNet/Endpoints/TasksOperations.cs +++ b/src/Docker.DotNet/Endpoints/TasksOperations.cs @@ -28,8 +28,7 @@ async Task> ITasksOperations.ListAsync(TasksListParameters p query = new QueryString(parameters); } - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "tasks", query, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject>(response.Body); + return await this._client.MakeRequestAsync>(this._client.NoErrorHandlers, HttpMethod.Get, "tasks", query, cancellationToken).ConfigureAwait(false); } async Task ITasksOperations.InspectAsync(string id, CancellationToken cancellationToken) @@ -39,8 +38,7 @@ async Task ITasksOperations.InspectAsync(string id, CancellationTo throw new ArgumentNullException(nameof(id)); } - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"tasks/{id}", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"tasks/{id}", cancellationToken).ConfigureAwait(false); } } } \ No newline at end of file diff --git a/src/Docker.DotNet/Endpoints/VolumeOperations.cs b/src/Docker.DotNet/Endpoints/VolumeOperations.cs index 69e74138f..3d4572c1a 100644 --- a/src/Docker.DotNet/Endpoints/VolumeOperations.cs +++ b/src/Docker.DotNet/Endpoints/VolumeOperations.cs @@ -1,6 +1,5 @@ using Docker.DotNet.Models; using System; -using System.IO; using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -18,15 +17,13 @@ internal VolumeOperations(DockerClient client) async Task IVolumeOperations.ListAsync(CancellationToken cancellationToken) { - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "volumes", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "volumes", cancellationToken).ConfigureAwait(false); } async Task IVolumeOperations.ListAsync(VolumesListParameters parameters, CancellationToken cancellationToken) { var queryParameters = parameters == null ? null : new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "volumes", queryParameters, null, cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "volumes", queryParameters, null, cancellationToken).ConfigureAwait(false); } async Task IVolumeOperations.CreateAsync(VolumesCreateParameters parameters, CancellationToken cancellationToken) @@ -37,8 +34,7 @@ async Task IVolumeOperations.CreateAsync(VolumesCreateParameters } var data = new JsonRequestContent(parameters, this._client.JsonSerializer); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "volumes/create", null, data, cancellationToken); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "volumes/create", null, data, cancellationToken); } async Task IVolumeOperations.InspectAsync(string name, CancellationToken cancellationToken) @@ -48,8 +44,7 @@ async Task IVolumeOperations.InspectAsync(string name, Cancellat throw new ArgumentNullException(nameof(name)); } - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"volumes/{name}", cancellationToken).ConfigureAwait(false); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"volumes/{name}", cancellationToken).ConfigureAwait(false); } Task IVolumeOperations.RemoveAsync(string name, bool? force, CancellationToken cancellationToken) @@ -65,8 +60,7 @@ Task IVolumeOperations.RemoveAsync(string name, bool? force, CancellationToken c async Task IVolumeOperations.PruneAsync(VolumesPruneParameters parameters, CancellationToken cancellationToken) { var queryParameters = parameters == null ? null : new QueryString(parameters); - var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, $"volumes/prune", queryParameters, cancellationToken); - return this._client.JsonSerializer.DeserializeObject(response.Body); + return await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "volumes/prune", queryParameters, cancellationToken); } } } \ No newline at end of file diff --git a/src/Docker.DotNet/JsonSerializer.cs b/src/Docker.DotNet/JsonSerializer.cs index c2143ad68..d3395e1c0 100644 --- a/src/Docker.DotNet/JsonSerializer.cs +++ b/src/Docker.DotNet/JsonSerializer.cs @@ -2,11 +2,13 @@ using System.Collections.Generic; using System.IO; using System.IO.Pipelines; +using System.Net.Http; using System.Net.Http.Json; using System.Runtime.CompilerServices; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; +using System.Threading.Tasks; namespace Docker.DotNet { @@ -63,7 +65,7 @@ private static bool TryParseJson(ref ReadOnlySequence buffer, out JsonDocu return false; } - public T DeserializeObject(string json) + public T DeserializeObject(byte[] json) { return System.Text.Json.JsonSerializer.Deserialize(json, _options); } @@ -77,5 +79,11 @@ public JsonContent GetHttpContent(T value) { return JsonContent.Create(value, options: _options); } + + public async Task DeserializeAsync(HttpContent content, CancellationToken token) + { + return await content.ReadFromJsonAsync(_options, token) + .ConfigureAwait(false); + } } }