diff --git a/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj b/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj index c569e156e..8644bb21b 100644 --- a/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj +++ b/benchmarks/RestSharp.Benchmarks/RestSharp.Benchmarks.csproj @@ -9,7 +9,8 @@ - + + diff --git a/gen/SourceGenerator/SourceGenerator.csproj b/gen/SourceGenerator/SourceGenerator.csproj index 9e63fcfeb..29310d2dd 100644 --- a/gen/SourceGenerator/SourceGenerator.csproj +++ b/gen/SourceGenerator/SourceGenerator.csproj @@ -11,11 +11,11 @@ - - + + - + diff --git a/src/RestSharp/Sync/AsyncHelpers.cs b/src/RestSharp/AsyncHelpers.cs similarity index 100% rename from src/RestSharp/Sync/AsyncHelpers.cs rename to src/RestSharp/AsyncHelpers.cs diff --git a/src/RestSharp/Request/RequestContent.cs b/src/RestSharp/Request/RequestContent.cs index 5a19f94fb..cfc7995ca 100644 --- a/src/RestSharp/Request/RequestContent.cs +++ b/src/RestSharp/Request/RequestContent.cs @@ -36,47 +36,44 @@ public RequestContent(RestClient client, RestRequest request) { _parameters = new RequestParameters(_request.Parameters.Union(_client.DefaultParameters)); } - public HttpContent BuildContent() - { - var postParameters = _parameters.GetContentParameters(_request.Method).ToArray(); + public HttpContent BuildContent() { + var postParameters = _parameters.GetContentParameters(_request.Method).ToArray(); var postParametersExists = postParameters.Length > 0; var bodyParametersExists = _request.TryGetBodyParameter(out var bodyParameter); - var filesExists = _request.Files.Any(); + var filesExists = _request.Files.Any(); - if (filesExists) - AddFiles(); + if (_request.HasFiles() || + BodyShouldBeMultipartForm(bodyParameter) || + filesExists || + _request.AlwaysMultipartFormData) { + Content = CreateMultipartFormDataContent(); + } + + if (filesExists) AddFiles(); - if (bodyParametersExists) - AddBody(postParametersExists, bodyParameter!); + if (bodyParametersExists) AddBody(postParametersExists, bodyParameter!); - if (postParametersExists) - AddPostParameters(postParameters); + if (postParametersExists) AddPostParameters(postParameters); AddHeaders(); return Content!; } - - void AddFiles() - { - // File uploading without multipart/form-data - if (_request.AlwaysSingleFileAsContent && _request.Files.Count == 1) - { - var fileParameter = _request.Files.First(); - Content = ToStreamContent(fileParameter); - return; - } - - var mpContent = new MultipartFormDataContent(GetOrSetFormBoundary()); - - foreach (var fileParameter in _request.Files) - mpContent.Add(ToStreamContent(fileParameter)); - - Content = mpContent; - } - - StreamContent ToStreamContent(FileParameter fileParameter) - { + + void AddFiles() { + // File uploading without multipart/form-data + if (_request is { AlwaysSingleFileAsContent: true, Files.Count: 1 }) { + var fileParameter = _request.Files.First(); + Content?.Dispose(); + Content = ToStreamContent(fileParameter); + return; + } + + var mpContent = Content as MultipartFormDataContent; + foreach (var fileParameter in _request.Files) mpContent!.Add(ToStreamContent(fileParameter)); + } + + StreamContent ToStreamContent(FileParameter fileParameter) { var stream = fileParameter.GetFile(); _streams.Add(stream); var streamContent = new StreamContent(stream); @@ -123,7 +120,9 @@ HttpContent GetSerialized() { } } - static bool BodyShouldBeMultipartForm(BodyParameter bodyParameter) { + static bool BodyShouldBeMultipartForm(BodyParameter? bodyParameter) { + if (bodyParameter == null) return false; + var bodyContentType = bodyParameter.ContentType.OrValue(bodyParameter.Name); return bodyParameter.Name.IsNotEmpty() && bodyParameter.Name != bodyContentType; } @@ -139,8 +138,7 @@ MultipartFormDataContent CreateMultipartFormDataContent() { return mpContent; } - void AddBody(bool hasPostParameters, BodyParameter bodyParameter) - { + void AddBody(bool hasPostParameters, BodyParameter bodyParameter) { var bodyContent = Serialize(bodyParameter); // we need to send the body diff --git a/src/RestSharp/RestClient.Async.cs b/src/RestSharp/RestClient.Async.cs index d3701e221..f3b738293 100644 --- a/src/RestSharp/RestClient.Async.cs +++ b/src/RestSharp/RestClient.Async.cs @@ -79,7 +79,10 @@ async Task ExecuteRequestAsync(RestRequest request, CancellationTo request.ValidateParameters(); var authenticator = request.Authenticator ?? Options.Authenticator; - if (authenticator != null) await authenticator.Authenticate(this, request).ConfigureAwait(false); + + if (authenticator != null) { + await authenticator.Authenticate(this, request).ConfigureAwait(false); + } using var requestContent = new RequestContent(this, request); diff --git a/src/RestSharp/RestClient.Extensions.Config.cs b/src/RestSharp/RestClient.Extensions.Config.cs deleted file mode 100644 index 3b4eda0a2..000000000 --- a/src/RestSharp/RestClient.Extensions.Config.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -using System.Text; -using RestSharp.Authenticators; - -namespace RestSharp; - -public static partial class RestClientExtensions { - [PublicAPI] - public static RestResponse Deserialize(this IRestClient client, RestResponse response) - => client.Serializers.Deserialize(response.Request, response, client.Options); - - [Obsolete("Set the RestClientOptions.Encode property instead")] - public static RestClient UseUrlEncoder(this RestClient client, Func encoder) - => throw new NotImplementedException("Set the RestClientOptions.Encode property instead"); - - [Obsolete("Set the RestClientOptions.EncodeQuery property instead")] - public static RestClient UseQueryEncoder(this RestClient client, Func queryEncoder) - => throw new NotImplementedException("Set the RestClientOptions.EncodeQuery property instead"); - - [Obsolete("Set the RestClientOptions.Authenticator property instead")] - public static RestClient UseAuthenticator(this RestClient client, IAuthenticator authenticator) - => throw new NotImplementedException("Set the RestClientOptions.Authenticator property instead"); -} diff --git a/src/RestSharp/RestClient.Extensions.Delete.cs b/src/RestSharp/RestClient.Extensions.Delete.cs new file mode 100644 index 000000000..32172e9e0 --- /dev/null +++ b/src/RestSharp/RestClient.Extensions.Delete.cs @@ -0,0 +1,106 @@ +// Copyright (c) .NET Foundation and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace RestSharp; + +public static partial class RestClientExtensions { + /// + /// Executes a DELETE-style request asynchronously, authenticating if needed + /// + /// + /// Request to be executed + /// Cancellation token + public static Task ExecuteDeleteAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) + => client.ExecuteAsync(request, Method.Delete, cancellationToken); + + /// + /// Executes a DELETE-style synchronously, authenticating if needed + /// + /// + /// Request to be executed + public static RestResponse ExecuteDelete(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Delete)); + + /// + /// Executes a DELETE-style request asynchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// The cancellation token + /// Deserialized response content + public static Task> ExecuteDeleteAsync( + this IRestClient client, + RestRequest request, + CancellationToken cancellationToken = default + ) + => client.ExecuteAsync(request, Method.Delete, cancellationToken); + + /// + /// Executes a DELETE-style request synchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// Deserialized response content + public static RestResponse ExecuteDelete(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Delete)); + + /// + /// Execute the request using DELETE HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// Expected result type + /// + public static async Task DeleteAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Delete, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError().Data; + } + + /// + /// Execute the request using DELETE HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Expected result type + /// + public static T? Delete(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.DeleteAsync(request)); + + /// + /// Execute the request using DELETE HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// + public static async Task DeleteAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Delete, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError(); + } + + /// + /// Execute the request using DELETE HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// + public static RestResponse Delete(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.DeleteAsync(request)); +} diff --git a/src/RestSharp/RestClient.Extensions.Get.cs b/src/RestSharp/RestClient.Extensions.Get.cs new file mode 100644 index 000000000..5bc52dff3 --- /dev/null +++ b/src/RestSharp/RestClient.Extensions.Get.cs @@ -0,0 +1,168 @@ +// Copyright (c) .NET Foundation and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace RestSharp; + +public static partial class RestClientExtensions { + /// + /// Executes a GET-style asynchronously, authenticating if needed. + /// + /// + /// Request to be executed + /// Cancellation token + public static Task ExecuteGetAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) + => client.ExecuteAsync(request, Method.Get, cancellationToken); + + /// + /// Executes a GET-style synchronously, authenticating if needed + /// + /// + /// Request to be executed + public static RestResponse ExecuteGet(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Get)); + + /// + /// Executes a GET-style request asynchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// Cancellation token + /// Deserialized response content + public static Task> ExecuteGetAsync( + this IRestClient client, + RestRequest request, + CancellationToken cancellationToken = default + ) + => client.ExecuteAsync(request, Method.Get, cancellationToken); + + /// + /// Executes a GET-style request synchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// Deserialized response content + public static RestResponse ExecuteGet(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Get)); + + /// + /// Execute the request using GET HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// + public static async Task GetAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteGetAsync(request, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError(); + } + + /// + /// Execute the request using GET HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// + public static RestResponse Get(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.GetAsync(request)); + + /// + /// Execute the request using GET HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// Expected result type + /// + public static async Task GetAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteGetAsync(request, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError().Data; + } + + /// + /// Execute the request using GET HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Expected result type + /// + public static T? Get(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.GetAsync(request)); + + /// + /// Calls the URL specified in the resource parameter, expecting a JSON response back. Deserializes and returns the response. + /// + /// RestClient instance + /// Resource URL + /// Cancellation token + /// Response object type + /// + public static Task GetJsonAsync(this IRestClient client, string resource, CancellationToken cancellationToken = default) { + var request = new RestRequest(resource); + return client.GetAsync(request, cancellationToken); + } + + /// + /// Calls the URL specified in the resource parameter, expecting a JSON response back. Deserializes and returns the response. + /// + /// RestClient instance + /// Resource URL + /// Response object type + /// Deserialized response object + public static TResponse? GetJson(this IRestClient client, string resource) + => AsyncHelpers.RunSync(() => client.GetJsonAsync(resource)); + + /// + /// Calls the URL specified in the resource parameter, expecting a JSON response back. Deserializes and returns the response. + /// + /// RestClient instance + /// Resource URL + /// Parameters to pass to the request + /// Cancellation token + /// Response object type + /// Deserialized response object + public static Task GetJsonAsync( + this IRestClient client, + string resource, + object parameters, + CancellationToken cancellationToken = default + ) { + var props = parameters.GetProperties(); + var request = new RestRequest(resource); + + foreach (var prop in props) { + Parameter parameter = resource.Contains($"{prop.Name}") + ? new UrlSegmentParameter(prop.Name, prop.Value!, prop.Encode) + : new QueryParameter(prop.Name, prop.Value, prop.Encode); + request.AddParameter(parameter); + } + + return client.GetAsync(request, cancellationToken); + } + + /// + /// Calls the URL specified in the resource parameter, expecting a JSON response back. Deserializes and returns the response. + /// + /// RestClient instance + /// Resource URL + /// Parameters to pass to the request + /// Response object type + /// Deserialized response object + public static TResponse? GetJson(this IRestClient client, string resource, object parameters) + => AsyncHelpers.RunSync(() => client.GetJsonAsync(resource, parameters)); +} diff --git a/src/RestSharp/RestClient.Extensions.Head.cs b/src/RestSharp/RestClient.Extensions.Head.cs new file mode 100644 index 000000000..c30402c02 --- /dev/null +++ b/src/RestSharp/RestClient.Extensions.Head.cs @@ -0,0 +1,106 @@ +// Copyright (c) .NET Foundation and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace RestSharp; + +public static partial class RestClientExtensions { + /// + /// Executes a HEAD-style request asynchronously, authenticating if needed + /// + /// + /// Request to be executed + /// Cancellation token + public static Task ExecuteHeadAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) + => client.ExecuteAsync(request, Method.Head, cancellationToken); + + /// + /// Executes a HEAD-style synchronously, authenticating if needed + /// + /// + /// Request to be executed + public static RestResponse ExecuteHead(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Head)); + + /// + /// Executes a HEAD-style request asynchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// The cancellation token + /// Deserialized response content + public static Task> ExecuteHeadAsync( + this IRestClient client, + RestRequest request, + CancellationToken cancellationToken = default + ) + => client.ExecuteAsync(request, Method.Head, cancellationToken); + + /// + /// Executes a HEAD-style request synchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// Deserialized response content + public static RestResponse ExecuteHead(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Head)); + + /// + /// Execute the request using HEAD HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// Expected result type + /// + public static async Task HeadAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Head, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError().Data; + } + + /// + /// Execute the request using HEAD HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Expected result type + /// + public static T? Head(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.HeadAsync(request)); + + /// + /// Execute the request using HEAD HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// + public static async Task HeadAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Head, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError(); + } + + /// + /// Execute the request using HEAD HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// + public static RestResponse Head(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.HeadAsync(request)); +} diff --git a/src/RestSharp/RestClient.Extensions.Json.cs b/src/RestSharp/RestClient.Extensions.Json.cs deleted file mode 100644 index 5a98a6821..000000000 --- a/src/RestSharp/RestClient.Extensions.Json.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -using System.Net; - -namespace RestSharp; - -public static partial class RestClientExtensions { - /// - /// Calls the URL specified in the resource parameter, expecting a JSON response back. Deserializes and returns the response. - /// - /// RestClient instance - /// Resource URL - /// Cancellation token - /// Response object type - /// - public static Task GetJsonAsync(this RestClient client, string resource, CancellationToken cancellationToken = default) { - var request = new RestRequest(resource); - return client.GetAsync(request, cancellationToken); - } - - /// - /// Calls the URL specified in the resource parameter, expecting a JSON response back. Deserializes and returns the response. - /// - /// RestClient instance - /// Resource URL - /// Parameters to pass to the request - /// Cancellation token - /// Response object type - /// Deserialized response object - public static Task GetJsonAsync( - this RestClient client, - string resource, - object parameters, - CancellationToken cancellationToken = default - ) { - var props = parameters.GetProperties(); - var request = new RestRequest(resource); - - foreach (var prop in props) { - Parameter parameter = resource.Contains($"{prop.Name}") - ? new UrlSegmentParameter(prop.Name, prop.Value!, prop.Encode) - : new QueryParameter(prop.Name, prop.Value, prop.Encode); - request.AddParameter(parameter); - } - - return client.GetAsync(request, cancellationToken); - } - - /// - /// Serializes the request object to JSON and makes a POST call to the resource specified in the resource parameter. - /// Expects a JSON response back, deserializes it to TResponse type and returns it. - /// - /// RestClient instance - /// Resource URL - /// Request object, must be serializable to JSON - /// Cancellation token - /// Request object type - /// Response object type - /// Deserialized response object - public static Task PostJsonAsync( - this RestClient client, - string resource, - TRequest request, - CancellationToken cancellationToken = default - ) where TRequest : class { - var restRequest = new RestRequest(resource).AddJsonBody(request); - return client.PostAsync(restRequest, cancellationToken); - } - - /// - /// Serializes the request object to JSON and makes a POST call to the resource specified in the resource parameter. - /// Expects no response back, just the status code. - /// - /// RestClient instance - /// Resource URL - /// Request object, must be serializable to JSON - /// Cancellation token - /// Request object type - /// Response status code - public static async Task PostJsonAsync( - this RestClient client, - string resource, - TRequest request, - CancellationToken cancellationToken = default - ) where TRequest : class { - var restRequest = new RestRequest(resource).AddJsonBody(request); - var response = await client.PostAsync(restRequest, cancellationToken).ConfigureAwait(false); - return response.StatusCode; - } - - /// - /// Serializes the request object to JSON and makes a PUT call to the resource specified in the resource parameter. - /// Expects a JSON response back, deserializes it to TResponse type and returns it. - /// - /// RestClient instance - /// Resource URL - /// Request object, must be serializable to JSON - /// Cancellation token - /// Request object type - /// Response object type - /// Deserialized response object - public static Task PutJsonAsync( - this RestClient client, - string resource, - TRequest request, - CancellationToken cancellationToken = default - ) where TRequest : class { - var restRequest = new RestRequest(resource).AddJsonBody(request); - return client.PutAsync(restRequest, cancellationToken); - } - - /// - /// Serializes the request object to JSON and makes a PUT call to the resource specified in the resource parameter. - /// Expects no response back, just the status code. - /// - /// RestClient instance - /// Resource URL - /// Request object, must be serializable to JSON - /// Cancellation token - /// Request object type - /// Response status code - public static async Task PutJsonAsync( - this RestClient client, - string resource, - TRequest request, - CancellationToken cancellationToken = default - ) where TRequest : class { - var restRequest = new RestRequest(resource).AddJsonBody(request); - var response = await client.PutAsync(restRequest, cancellationToken).ConfigureAwait(false); - return response.StatusCode; - } -} diff --git a/src/RestSharp/RestClient.Extensions.Options.cs b/src/RestSharp/RestClient.Extensions.Options.cs new file mode 100644 index 000000000..7163fcf51 --- /dev/null +++ b/src/RestSharp/RestClient.Extensions.Options.cs @@ -0,0 +1,106 @@ +// Copyright (c) .NET Foundation and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace RestSharp; + +public static partial class RestClientExtensions { + /// + /// Executes a OPTIONS-style request asynchronously, authenticating if needed + /// + /// + /// Request to be executed + /// Cancellation token + public static Task ExecuteOptionsAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) + => client.ExecuteAsync(request, Method.Options, cancellationToken); + + /// + /// Executes a OPTIONS-style synchronously, authenticating if needed + /// + /// + /// Request to be executed + public static RestResponse ExecuteOptions(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Options)); + + /// + /// Executes a OPTIONS-style request asynchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// The cancellation token + /// Deserialized response content + public static Task> ExecuteOptionsAsync( + this IRestClient client, + RestRequest request, + CancellationToken cancellationToken = default + ) + => client.ExecuteAsync(request, Method.Options, cancellationToken); + + /// + /// Executes a OPTIONS-style request synchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// Deserialized response content + public static RestResponse ExecuteOptions(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Options)); + + /// + /// Execute the request using OPTIONS HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// + public static async Task OptionsAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Options, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError(); + } + + /// + /// Execute the request using OPTIONS HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// + public static RestResponse Options(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.OptionsAsync(request)); + + /// + /// Execute the request using OPTIONS HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// Expected result type + /// + public static async Task OptionsAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Options, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError().Data; + } + + /// + /// Execute the request using OPTIONS HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Expected result type + /// + public static T? Options(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.OptionsAsync(request)); +} diff --git a/src/RestSharp/RestClient.Extensions.Patch.cs b/src/RestSharp/RestClient.Extensions.Patch.cs new file mode 100644 index 000000000..44547ab7f --- /dev/null +++ b/src/RestSharp/RestClient.Extensions.Patch.cs @@ -0,0 +1,108 @@ +// Copyright (c) .NET Foundation and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace RestSharp; + +public static partial class RestClientExtensions { + /// + /// Executes a PUT-style request asynchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// The cancellation token + /// Deserialized response content + public static Task> ExecutePatchAsync( + this IRestClient client, + RestRequest request, + CancellationToken cancellationToken = default + ) + => client.ExecuteAsync(request, Method.Patch, cancellationToken); + + /// + /// Executes a PATCH-style request synchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// Deserialized response content + public static RestResponse ExecutePatch(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Patch)); + + /// + /// Executes a PATCH-style request asynchronously, authenticating if needed + /// + /// + /// Request to be executed + /// Cancellation token + public static Task ExecutePatchAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) + => client.ExecuteAsync(request, Method.Patch, cancellationToken); + + /// + /// Executes a PATCH-style synchronously, authenticating if needed + /// + /// + /// Request to be executed + public static RestResponse ExecutePatch(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Patch)); + + /// + /// Execute the request using PATCH HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// Expected result type + /// + public static async Task PatchAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Patch, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError().Data; + } + + /// + /// Execute the request using PATCH HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Expected result type + /// + [PublicAPI] + public static T? Patch(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.PatchAsync(request)); + + /// + /// Execute the request using PATCH HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// + public static async Task PatchAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Patch, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError(); + } + + /// + /// Execute the request using PATCH HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// + [PublicAPI] + public static RestResponse Patch(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.PatchAsync(request)); +} diff --git a/src/RestSharp/RestClient.Extensions.Post.cs b/src/RestSharp/RestClient.Extensions.Post.cs new file mode 100644 index 000000000..beddd15a5 --- /dev/null +++ b/src/RestSharp/RestClient.Extensions.Post.cs @@ -0,0 +1,175 @@ +// Copyright (c) .NET Foundation and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System.Net; + +namespace RestSharp; + +public static partial class RestClientExtensions { + /// + /// Executes a POST-style request asynchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// The cancellation token + /// Deserialized response content + public static Task> ExecutePostAsync( + this IRestClient client, + RestRequest request, + CancellationToken cancellationToken = default + ) + => client.ExecuteAsync(request, Method.Post, cancellationToken); + + /// + /// Executes a POST-style request synchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// Deserialized response content + public static RestResponse ExecutePost(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Post)); + + /// + /// Executes a POST-style asynchronously, authenticating if needed + /// + /// + /// Request to be executed + /// Cancellation token + public static Task ExecutePostAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) + => client.ExecuteAsync(request, Method.Post, cancellationToken); + + /// + /// Executes a POST-style synchronously, authenticating if needed + /// + /// + /// Request to be executed + public static RestResponse ExecutePost(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Post)); + + /// + /// Execute the request using POST HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// Expected result type + /// + public static async Task PostAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecutePostAsync(request, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError().Data; + } + + /// + /// Execute the request using POST HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Expected result type + /// + public static T? Post(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.PostAsync(request)); + + /// + /// Execute the request using POST HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// + public static async Task PostAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecutePostAsync(request, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError(); + } + + /// + /// Execute the request using POST HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// + public static RestResponse Post(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.PostAsync(request)); + + /// + /// Serializes the request object to JSON and makes a POST call to the resource specified in the resource parameter. + /// Expects a JSON response back, deserializes it to TResponse type and returns it. + /// + /// RestClient instance + /// Resource URL + /// Request object, must be serializable to JSON + /// Cancellation token + /// Request object type + /// Response object type + /// Deserialized response object + public static Task PostJsonAsync( + this IRestClient client, + string resource, + TRequest request, + CancellationToken cancellationToken = default + ) where TRequest : class { + var restRequest = new RestRequest(resource).AddJsonBody(request); + return client.PostAsync(restRequest, cancellationToken); + } + + /// + /// Serializes the request object to JSON and makes a POST call to the resource specified in the resource parameter. + /// Expects a JSON response back, deserializes it to TResponse type and returns it. + /// + /// RestClient instance + /// Resource URL + /// Request object, must be serializable to JSON + /// Request object type + /// Response object type + /// Deserialized response object + public static TResponse? PostJson(this IRestClient client, string resource, TRequest request) where TRequest : class + => AsyncHelpers.RunSync(() => client.PostJsonAsync(resource, request)); + + /// + /// Serializes the request object to JSON and makes a POST call to the resource specified in the resource parameter. + /// Expects no response back, just the status code. + /// + /// RestClient instance + /// Resource URL + /// Request object, must be serializable to JSON + /// Cancellation token + /// Request object type + /// Response status code + public static async Task PostJsonAsync( + this IRestClient client, + string resource, + TRequest request, + CancellationToken cancellationToken = default + ) where TRequest : class { + var restRequest = new RestRequest(resource).AddJsonBody(request); + var response = await client.PostAsync(restRequest, cancellationToken).ConfigureAwait(false); + return response.StatusCode; + } + + /// + /// Serializes the request object to JSON and makes a POST call to the resource specified in the resource parameter. + /// Expects no response back, just the status code. + /// + /// RestClient instance + /// Resource URL + /// Request object, must be serializable to JSON + /// Request object type + /// Response status code + public static HttpStatusCode PostJson(this IRestClient client, string resource, TRequest request) where TRequest : class + => AsyncHelpers.RunSync(() => client.PostJsonAsync(resource, request)); +} diff --git a/src/RestSharp/RestClient.Extensions.Put.cs b/src/RestSharp/RestClient.Extensions.Put.cs new file mode 100644 index 000000000..44a37d768 --- /dev/null +++ b/src/RestSharp/RestClient.Extensions.Put.cs @@ -0,0 +1,175 @@ +// Copyright (c) .NET Foundation and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System.Net; + +namespace RestSharp; + +public static partial class RestClientExtensions { + /// + /// Executes a PUT-style request asynchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// The cancellation token + /// Deserialized response content + public static Task> ExecutePutAsync( + this IRestClient client, + RestRequest request, + CancellationToken cancellationToken = default + ) + => client.ExecuteAsync(request, Method.Put, cancellationToken); + + /// + /// Executes a PUT-style request synchronously, authenticating if needed. + /// The response content then gets deserialized to T. + /// + /// Target deserialization type + /// + /// Request to be executed + /// Deserialized response content + public static RestResponse ExecutePut(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Put)); + + /// + /// Executes a PUP-style request asynchronously, authenticating if needed + /// + /// + /// Request to be executed + /// Cancellation token + public static Task ExecutePutAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) + => client.ExecuteAsync(request, Method.Put, cancellationToken); + + /// + /// Executes a PUT-style synchronously, authenticating if needed + /// + /// + /// Request to be executed + public static RestResponse ExecutePut(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Put)); + + /// + /// Execute the request using PUT HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// Expected result type + /// Deserialaized response + public static async Task PutAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Put, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError().Data; + } + + /// + /// Execute the request using PUT HTTP method. Exception will be thrown if the request does not succeed. + /// The response data is deserialized to the Data property of the returned response object. + /// + /// RestClient instance + /// The request + /// Expected result type + /// + public static T? Put(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.PutAsync(request)); + + /// + /// Execute the request using PUT HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// Cancellation token + /// + public static async Task PutAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { + var response = await client.ExecuteAsync(request, Method.Put, cancellationToken).ConfigureAwait(false); + return response.ThrowIfError(); + } + + /// + /// Execute the request using PUT HTTP method. Exception will be thrown if the request does not succeed. + /// + /// RestClient instance + /// The request + /// + public static RestResponse Put(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.PutAsync(request)); + + /// + /// Serializes the request object to JSON and makes a PUT call to the resource specified in the resource parameter. + /// Expects a JSON response back, deserializes it to TResponse type and returns it. + /// + /// RestClient instance + /// Resource URL + /// Request object, must be serializable to JSON + /// Cancellation token + /// Request object type + /// Response object type + /// Deserialized response object + public static Task PutJsonAsync( + this IRestClient client, + string resource, + TRequest request, + CancellationToken cancellationToken = default + ) where TRequest : class { + var restRequest = new RestRequest(resource).AddJsonBody(request); + return client.PutAsync(restRequest, cancellationToken); + } + + /// + /// Serializes the request object to JSON and makes a PUT call to the resource specified in the resource parameter. + /// Expects a JSON response back, deserializes it to TResponse type and returns it. + /// + /// RestClient instance + /// Resource URL + /// Request object, must be serializable to JSON + /// Request object type + /// Response object type + /// Deserialized response object + public static TResponse? PutJson(this IRestClient client, string resource, TRequest request) where TRequest : class + => AsyncHelpers.RunSync(() => client.PutJsonAsync(resource, request)); + + /// + /// Serializes the request object to JSON and makes a PUT call to the resource specified in the resource parameter. + /// Expects no response back, just the status code. + /// + /// RestClient instance + /// Resource URL + /// Request object, must be serializable to JSON + /// Cancellation token + /// Request object type + /// Response status code + public static async Task PutJsonAsync( + this IRestClient client, + string resource, + TRequest request, + CancellationToken cancellationToken = default + ) where TRequest : class { + var restRequest = new RestRequest(resource).AddJsonBody(request); + var response = await client.PutAsync(restRequest, cancellationToken).ConfigureAwait(false); + return response.StatusCode; + } + + /// + /// Serializes the request object to JSON and makes a PUT call to the resource specified in the resource parameter. + /// Expects no response back, just the status code. + /// + /// RestClient instance + /// Resource URL + /// Request object, must be serializable to JSON + /// Request object type + /// Response status code + public static HttpStatusCode PutJson(this IRestClient client, string resource, TRequest request) where TRequest : class + => AsyncHelpers.RunSync(() => client.PutJsonAsync(resource, request)); +} diff --git a/src/RestSharp/RestClient.Extensions.cs b/src/RestSharp/RestClient.Extensions.cs index c03321170..941db8585 100644 --- a/src/RestSharp/RestClient.Extensions.cs +++ b/src/RestSharp/RestClient.Extensions.cs @@ -19,92 +19,36 @@ namespace RestSharp; [PublicAPI] public static partial class RestClientExtensions { - /// - /// Executes a GET-style request asynchronously, authenticating if needed. - /// The response content then gets deserialized to T. - /// - /// Target deserialization type - /// - /// Request to be executed - /// Cancellation token - /// Deserialized response content - public static Task> ExecuteGetAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) - => client.ExecuteAsync(request, Method.Get, cancellationToken); - - /// - /// Executes a GET-style asynchronously, authenticating if needed - /// - /// - /// Request to be executed - /// Cancellation token - public static Task ExecuteGetAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) - => client.ExecuteAsync(request, Method.Get, cancellationToken); + [PublicAPI] + public static RestResponse Deserialize(this IRestClient client, RestResponse response) + => client.Serializers.Deserialize(response.Request, response, client.Options); /// - /// Executes a POST-style request asynchronously, authenticating if needed. - /// The response content then gets deserialized to T. + /// Executes the request asynchronously, authenticating if needed /// /// Target deserialization type /// /// Request to be executed - /// The cancellation token - /// Deserialized response content - public static Task> ExecutePostAsync( - this IRestClient client, - RestRequest request, - CancellationToken cancellationToken = default - ) - => client.ExecuteAsync(request, Method.Post, cancellationToken); - - /// - /// Executes a POST-style asynchronously, authenticating if needed - /// - /// - /// Request to be executed /// Cancellation token - public static Task ExecutePostAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) - => client.ExecuteAsync(request, Method.Post, cancellationToken); - - /// - /// Executes a PUT-style request asynchronously, authenticating if needed. - /// The response content then gets deserialized to T. - /// - /// Target deserialization type - /// - /// Request to be executed - /// The cancellation token - /// Deserialized response content - public static Task> ExecutePutAsync( + public static async Task> ExecuteAsync( this IRestClient client, RestRequest request, CancellationToken cancellationToken = default - ) - => client.ExecuteAsync(request, Method.Put, cancellationToken); + ) { + if (request == null) throw new ArgumentNullException(nameof(request)); - /// - /// Executes a PUP-style asynchronously, authenticating if needed - /// - /// - /// Request to be executed - /// Cancellation token - public static Task ExecutePutAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) - => client.ExecuteAsync(request, Method.Put, cancellationToken); + var response = await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); + return client.Serializers.Deserialize(request, response, client.Options); + } /// - /// Executes the request asynchronously, authenticating if needed + /// Executes the request synchronously, authenticating if needed /// /// Target deserialization type /// /// Request to be executed - /// Cancellation token - public static async Task> ExecuteAsync( - this IRestClient client, - RestRequest request, - CancellationToken cancellationToken = default - ) { - var response = await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); - return client.Serializers.Deserialize(request, response, client.Options); - } + public static RestResponse Execute(this IRestClient client, RestRequest request) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request)); /// /// Executes the request asynchronously, authenticating if needed @@ -125,6 +69,15 @@ public static Task ExecuteAsync( return client.ExecuteAsync(request, cancellationToken); } + /// + /// Executes the request synchronously, authenticating if needed + /// + /// + /// Request to be executed + /// Override the request method + public static RestResponse Execute(this IRestClient client, RestRequest request, Method httpMethod) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, httpMethod)); + /// /// Executes the request asynchronously, authenticating if needed /// @@ -146,140 +99,14 @@ public static Task> ExecuteAsync( } /// - /// Execute the request using GET HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. + /// Executes the request synchronously, authenticating if needed /// - /// RestClient instance - /// The request - /// Cancellation token - /// Expected result type - /// - public static async Task GetAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteGetAsync(request, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError().Data; - } - - public static async Task GetAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteGetAsync(request, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError(); - } - - /// - /// Execute the request using POST HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Cancellation token - /// Expected result type - /// - public static async Task PostAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecutePostAsync(request, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError().Data; - } - - public static RestResponse Post(this IRestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.PostAsync(request)); - - public static async Task PostAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecutePostAsync(request, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError(); - } - - /// - /// Execute the request using PUT HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Cancellation token - /// Expected result type - /// - public static async Task PutAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Put, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError().Data; - } - - public static async Task PutAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Put, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError(); - } - - /// - /// Execute the request using HEAD HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Cancellation token - /// Expected result type - /// - public static async Task HeadAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Head, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError().Data; - } - - public static async Task HeadAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Head, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError(); - } - - /// - /// Execute the request using OPTIONS HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Cancellation token - /// Expected result type - /// - public static async Task OptionsAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Options, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError().Data; - } - - public static async Task OptionsAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Options, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError(); - } - - /// - /// Execute the request using PATCH HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Cancellation token - /// Expected result type - /// - public static async Task PatchAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Patch, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError().Data; - } - - public static async Task PatchAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Patch, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError(); - } - - /// - /// Execute the request using DELETE HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Cancellation token - /// Expected result type - /// - public static async Task DeleteAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Delete, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError().Data; - } - - public static async Task DeleteAsync(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) { - var response = await client.ExecuteAsync(request, Method.Delete, cancellationToken).ConfigureAwait(false); - return response.ThrowIfError(); - } + /// Target deserialization type + /// + /// Request to be executed + /// Override the request method + public static RestResponse Execute(this IRestClient client, RestRequest request, Method httpMethod) + => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, httpMethod)); /// /// A specialized method to download files. @@ -298,6 +125,25 @@ public static async Task DeleteAsync(this IRestClient client, Rest return stream == null ? null : await stream.ReadAsBytes(cancellationToken).ConfigureAwait(false); } + /// + /// A specialized method to download files as streams. + /// + /// + /// Pre-configured request instance. + /// The cancellation token + /// The downloaded stream. + [PublicAPI] + public static Stream? DownloadStream(this IRestClient client, RestRequest request, CancellationToken cancellationToken = default) + => AsyncHelpers.RunSync(() => client.DownloadStreamAsync(request, cancellationToken)); + + /// + /// A specialized method to download files. + /// + /// RestClient instance + /// Pre-configured request instance. + /// The downloaded file. + public static byte[]? DownloadData(this IRestClient client, RestRequest request) => AsyncHelpers.RunSync(() => client.DownloadDataAsync(request)); + /// /// Reads a stream returned by the specified endpoint, deserializes each line to JSON and returns each object asynchronously. /// It is required for each JSON object to be returned in a single line. @@ -338,5 +184,4 @@ [EnumeratorCancellation] CancellationToken cancellationToken yield return serializer.Deserializer.Deserialize(response)!; } } - } diff --git a/src/RestSharp/RestSharp.csproj b/src/RestSharp/RestSharp.csproj index 1d9e0d915..a339d9944 100644 --- a/src/RestSharp/RestSharp.csproj +++ b/src/RestSharp/RestSharp.csproj @@ -3,7 +3,7 @@ true - + @@ -17,12 +17,6 @@ - - RestClient.Extensions.cs - - - RestClient.Extensions.cs - RestClient.Extensions.cs @@ -35,6 +29,27 @@ PropertyCache.cs + + RestClient.Extensions.cs + + + RestClient.Extensions.cs + + + RestClient.Extensions.cs + + + RestClient.Extensions.cs + + + RestClient.Extensions.cs + + + RestClient.Extensions.cs + + + RestClient.Extensions.cs + diff --git a/src/RestSharp/Sync/RestClient.Sync.cs b/src/RestSharp/Sync/RestClient.Sync.cs deleted file mode 100644 index 50b4e6557..000000000 --- a/src/RestSharp/Sync/RestClient.Sync.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -namespace RestSharp; - -public static partial class RestClientExtensions { - /// - /// Executes the request synchronously, authenticating if needed - /// - /// - /// Request to be executed - /// The cancellation token - public static RestResponse Execute(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, cancellationToken)); - - /// - /// A specialized method to download files as streams. - /// - /// - /// Pre-configured request instance. - /// The cancellation token - /// The downloaded stream. - [PublicAPI] - public static Stream? DownloadStream(this RestClient client, RestRequest request, CancellationToken cancellationToken = default) - => AsyncHelpers.RunSync(() => client.DownloadStreamAsync(request, cancellationToken)); -} diff --git a/src/RestSharp/Sync/RestClientExtensions.Sync.Json.cs b/src/RestSharp/Sync/RestClientExtensions.Sync.Json.cs deleted file mode 100644 index 25b265f09..000000000 --- a/src/RestSharp/Sync/RestClientExtensions.Sync.Json.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -using System.Net; - -namespace RestSharp; - -public static partial class RestClientExtensions { - /// - /// Calls the URL specified in the resource parameter, expecting a JSON response back. Deserializes and returns the response. - /// - /// RestClient instance - /// Resource URL - /// Response object type - /// Deserialized response object - public static TResponse? GetJson( - this RestClient client, - string resource) - => AsyncHelpers.RunSync(() => client.GetJsonAsync(resource)); - - /// - /// Calls the URL specified in the resource parameter, expecting a JSON response back. Deserializes and returns the response. - /// - /// RestClient instance - /// Resource URL - /// Parameters to pass to the request - /// Response object type - /// Deserialized response object - public static TResponse? GetJson( - this RestClient client, - string resource, - object parameters) - => AsyncHelpers.RunSync(() => client.GetJsonAsync(resource, parameters)); - - /// - /// Serializes the request object to JSON and makes a POST call to the resource specified in the resource parameter. - /// Expects a JSON response back, deserializes it to TResponse type and returns it. - /// - /// RestClient instance - /// Resource URL - /// Request object, must be serializable to JSON - /// Request object type - /// Response object type - /// Deserialized response object - public static TResponse? PostJson( - this RestClient client, - string resource, - TRequest request - ) where TRequest : class - => AsyncHelpers.RunSync(() => client.PostJsonAsync(resource, request)); - - /// - /// Serializes the request object to JSON and makes a POST call to the resource specified in the resource parameter. - /// Expects no response back, just the status code. - /// - /// RestClient instance - /// Resource URL - /// Request object, must be serializable to JSON - /// Request object type - /// Response status code - public static HttpStatusCode PostJson( - this RestClient client, - string resource, - TRequest request - ) where TRequest : class - => AsyncHelpers.RunSync(() => client.PostJsonAsync(resource, request)); - - /// - /// Serializes the request object to JSON and makes a PUT call to the resource specified in the resource parameter. - /// Expects a JSON response back, deserializes it to TResponse type and returns it. - /// - /// RestClient instance - /// Resource URL - /// Request object, must be serializable to JSON - /// Request object type - /// Response object type - /// Deserialized response object - public static TResponse? PutJson( - this RestClient client, - string resource, - TRequest request - ) where TRequest : class - => AsyncHelpers.RunSync(() => client.PutJsonAsync(resource, request)); - - /// - /// Serializes the request object to JSON and makes a PUT call to the resource specified in the resource parameter. - /// Expects no response back, just the status code. - /// - /// RestClient instance - /// Resource URL - /// Request object, must be serializable to JSON - /// Request object type - /// Response status code - public static HttpStatusCode PutJson( - this RestClient client, - string resource, - TRequest request - ) where TRequest : class - => AsyncHelpers.RunSync(() => client.PutJsonAsync(resource, request)); -} \ No newline at end of file diff --git a/src/RestSharp/Sync/RestClientExtensions.Sync.cs b/src/RestSharp/Sync/RestClientExtensions.Sync.cs deleted file mode 100644 index 58be4e927..000000000 --- a/src/RestSharp/Sync/RestClientExtensions.Sync.cs +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) .NET Foundation and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -namespace RestSharp; - -[PublicAPI] -public static class RestClientSyncExtensions { - /// - /// Executes a GET-style request synchronously, authenticating if needed. - /// The response content then gets deserialized to T. - /// - /// Target deserialization type - /// - /// Request to be executed - /// Deserialized response content - public static RestResponse ExecuteGet(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Get)); - - /// - /// Executes a GET-style synchronously, authenticating if needed - /// - /// - /// Request to be executed - public static RestResponse ExecuteGet(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Get)); - - /// - /// Executes a POST-style request synchronously, authenticating if needed. - /// The response content then gets deserialized to T. - /// - /// Target deserialization type - /// - /// Request to be executed - /// Deserialized response content - public static RestResponse ExecutePost( - this RestClient client, - RestRequest request - ) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Post)); - - /// - /// Executes a POST-style synchronously, authenticating if needed - /// - /// - /// Request to be executed - public static RestResponse ExecutePost(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Post)); - - /// - /// Executes a PUT-style request synchronously, authenticating if needed. - /// The response content then gets deserialized to T. - /// - /// Target deserialization type - /// - /// Request to be executed - /// Deserialized response content - public static RestResponse ExecutePut( - this RestClient client, - RestRequest request - ) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Put)); - - /// - /// Executes a PUP-style synchronously, authenticating if needed - /// - /// - /// Request to be executed - public static RestResponse ExecutePut(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, Method.Put)); - - /// - /// Executes the request synchronously, authenticating if needed - /// - /// Target deserialization type - /// - /// Request to be executed - public static RestResponse Execute( - this RestClient client, - RestRequest request - ) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request)); - - /// - /// Executes the request synchronously, authenticating if needed - /// - /// - /// Request to be executed - /// Override the request method - public static RestResponse Execute( - this RestClient client, - RestRequest request, - Method httpMethod - ) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, httpMethod)); - - /// - /// Executes the request synchronously, authenticating if needed - /// - /// Target deserialization type - /// - /// Request to be executed - /// Override the request method - public static RestResponse Execute( - this RestClient client, - RestRequest request, - Method httpMethod - ) - => AsyncHelpers.RunSync(() => client.ExecuteAsync(request, httpMethod)); - - /// - /// Execute the request using GET HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Expected result type - /// - public static T? Get(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.GetAsync(request)); - - public static RestResponse Get(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.GetAsync(request)); - - /// - /// Execute the request using POST HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Expected result type - /// - public static T? Post(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.PostAsync(request)); - - /// - /// Execute the request using PUT HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Expected result type - /// - public static T? Put(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.PutAsync(request)); - - public static RestResponse Put(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.PutAsync(request)); - - /// - /// Execute the request using HEAD HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Expected result type - /// - public static T? Head(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.HeadAsync(request)); - - public static RestResponse Head(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.HeadAsync(request)); - - /// - /// Execute the request using OPTIONS HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Expected result type - /// - public static T? Options(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.OptionsAsync(request)); - - public static RestResponse Options(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.OptionsAsync(request)); - - /// - /// Execute the request using PATCH HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Expected result type - /// - [PublicAPI] - public static T? Patch(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.PatchAsync(request)); - - [PublicAPI] - public static RestResponse Patch(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.PatchAsync(request)); - - /// - /// Execute the request using DELETE HTTP method. Exception will be thrown if the request does not succeed. - /// The response data is deserialized to the Data property of the returned response object. - /// - /// RestClient instance - /// The request - /// Expected result type - /// - public static T? Delete(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.DeleteAsync(request)); - - public static RestResponse Delete(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.DeleteAsync(request)); - - /// - /// A specialized method to download files. - /// - /// RestClient instance - /// Pre-configured request instance. - /// The downloaded file. - public static byte[]? DownloadData(this RestClient client, RestRequest request) - => AsyncHelpers.RunSync(() => client.DownloadDataAsync(request)); -} diff --git a/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj b/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj index 6cf43fa35..faa763b3d 100644 --- a/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj +++ b/test/RestSharp.Tests.Integrated/RestSharp.Tests.Integrated.csproj @@ -17,7 +17,7 @@ - +