diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 4637c75..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.github/workflows/build-and-test-develop.yml b/.github/workflows/build-and-test-develop.yml index c4ff57a..847db89 100644 --- a/.github/workflows/build-and-test-develop.yml +++ b/.github/workflows/build-and-test-develop.yml @@ -14,7 +14,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: - dotnet-version: 6.0.400 + dotnet-version: 8.0.302 - name: Install dependencies run: dotnet restore @@ -26,7 +26,7 @@ jobs: - name: Moving test coverage result to root folder run: | - mv Tests/TestResults/**/coverage.cobertura.xml ./ + mv Rx.Http.Tests/TestResults/**/coverage.cobertura.xml ./ - name: Run codacy-coverage-reporter uses: codacy/codacy-coverage-reporter-action@v1 diff --git a/.github/workflows/build-test-publish.yml b/.github/workflows/build-test-publish.yml index 64832f6..45e9be4 100644 --- a/.github/workflows/build-test-publish.yml +++ b/.github/workflows/build-test-publish.yml @@ -13,7 +13,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: - dotnet-version: 6.0.400 + dotnet-version: 8.0.302 source-url: https://nuget.pkg.github.com/lucassklp/index.json env: NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} @@ -26,7 +26,7 @@ jobs: - name: Moving test coverage result to root folder run: | - mv Tests/TestResults/**/coverage.cobertura.xml ./ + mv Rx.Http.Tests/TestResults/**/coverage.cobertura.xml ./ - name: Send test coverage to Codacy uses: codacy/codacy-coverage-reporter-action@v1 diff --git a/.gitignore b/.gitignore index 1e23adb..9f86d7e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .idea .vs .vscode +.DS_Store diff --git a/Models/Consumers/PostmanConsumer.cs b/Models/Consumers/PostmanConsumer.cs index 2755d14..c29b96f 100644 --- a/Models/Consumers/PostmanConsumer.cs +++ b/Models/Consumers/PostmanConsumer.cs @@ -13,7 +13,7 @@ public PostmanConsumer(HttpClient httpClient) : base(httpClient, null) httpClient.BaseAddress = new Uri("https://postman-echo.com"); } - public IObservable GetWithQueryString(IDictionary query) + public IObservable GetWithQueryString(IDictionary query) { return Get("get", opts => { @@ -21,16 +21,7 @@ public IObservable GetWithQueryString(IDictionary }); } - public IObservable GetWithQueryString(IDictionary> query) - { - return Get("get", opts => - { - opts.AddQueryString(query); - }); - } - - - public IObservable GetWithHeaders(IDictionary headers) + public IObservable GetWithHeaders(IDictionary headers) { return Get("get", opts => { diff --git a/Models/Models.csproj b/Models/Models.csproj index 19b678d..39b9231 100644 --- a/Models/Models.csproj +++ b/Models/Models.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 false diff --git a/README.md b/README.md index 08f7dbb..39fce9e 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,13 @@ A lightweight library that is inpired in [Angular 2+ Http Client](https://angula If you are using Package Manager: ```bash -Install-Package Rx.Http -Version 2.0.3 +Install-Package Rx.Http -Version 2.1.0 ``` If you are using .NET CLI ```bash -dotnet add package Rx.Http --version 2.0.3 +dotnet add package Rx.Http --version 2.1.0 ``` ## Example of use diff --git a/Rx.Http.Tests/ConsumersTests.cs b/Rx.Http.Tests/ConsumersTests.cs new file mode 100644 index 0000000..2471c2d --- /dev/null +++ b/Rx.Http.Tests/ConsumersTests.cs @@ -0,0 +1,116 @@ +using Models; +using Models.Consumers; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace Rx.Http.Tests +{ + public class ConsumersTests + { + private readonly Injector injector; + public ConsumersTests() + { + injector = new Injector(); + } + + [Fact] + public async Task CheckIfRequestIsWorking() + { + var tmdbConsumer = injector.Get(); + var response = await tmdbConsumer.ListMovies(); + + Assert.NotNull(response); + } + + [Fact] + public async Task CheckSameRequestTwice() + { + var tmdbConsumer = injector.Get(); + var response1 = await tmdbConsumer.ListMovies(); + var response2 = await tmdbConsumer.ListMovies(); + + Assert.NotNull(response1); + Assert.NotNull(response2); + } + + [Fact] + public async Task TestPostWithBody() + { + var postmanConsumer = injector.Get(); + + var todo = new Todo + { + Id = 12, + Title = "Testing with special characters: àáç~ã*+ü?<>!ºªª", + IsCompleted = true, + UserId = 20 + }; + var response = await postmanConsumer.Post(todo); + + Assert.True(response.Data.Equals(todo)); + } + + [Fact] + public async Task TestQueryStrings() + { + var postmanConsumer = injector.Get(); + + var queryStrings = new Dictionary + { + { "Foo", "Bar" }, + { "User", "John Doe" }, + { "Characters", "*&�%6dbajs&@#chv73*(#Y" }, + { "Boolean", true }, + { "Int", 1 }, + { "Float", 1.8129f }, + { "Double", 1.8129d }, + }; + + var headers = await postmanConsumer.GetWithQueryString(queryStrings); + + Assert.Equal(headers.Args, new Dictionary + { + { "Foo", "Bar" }, + { "User", "John Doe" }, + { "Characters", "*&�%6dbajs&@#chv73*(#Y" }, + { "Boolean", "true" }, + { "Int", "1" }, + { "Float", "1.8129" }, + { "Double", "1.8129" }, + }); + } + + [Fact] + public async Task TestHeaders() + { + var postmanConsumer = injector.Get(); + + var headers = new Dictionary + { + { "Foo", "Bar" }, + { "User", "John Doe" }, + { "Boolean", true }, + { "Int", 1 }, + { "Float", 1.8129f }, + { "Double", 1.8129d }, + }; + + var expected = new Dictionary + { + { "foo", "Bar" }, + { "user", "John Doe" }, + { "boolean", "true" }, + { "int", "1" }, + { "float", "1.8129" }, + { "double", "1.8129" }, + }; + + var response = await postmanConsumer.GetWithHeaders(headers); + var valid = expected.All(pair => response.Headers.ContainsKey(pair.Key) && response.Headers[pair.Key] == pair.Value); + Assert.True(valid); + } + } +} diff --git a/Tests/HttpLoggerBaseTests.cs b/Rx.Http.Tests/HttpLoggerBaseTests.cs similarity index 99% rename from Tests/HttpLoggerBaseTests.cs rename to Rx.Http.Tests/HttpLoggerBaseTests.cs index 1420418..7430c5b 100644 --- a/Tests/HttpLoggerBaseTests.cs +++ b/Rx.Http.Tests/HttpLoggerBaseTests.cs @@ -7,7 +7,7 @@ using System.Text; using Xunit; -namespace Tests +namespace Rx.Http.Tests { public class HttpLoggerBaseTests { diff --git a/Tests/InjectionTests.cs b/Rx.Http.Tests/InjectionTests.cs similarity index 96% rename from Tests/InjectionTests.cs rename to Rx.Http.Tests/InjectionTests.cs index 7c68eb9..7d992ea 100644 --- a/Tests/InjectionTests.cs +++ b/Rx.Http.Tests/InjectionTests.cs @@ -2,7 +2,7 @@ using Rx.Http; using Xunit; -namespace Tests +namespace Rx.Http.Tests { public class InjectionTests { diff --git a/Tests/Injector.cs b/Rx.Http.Tests/Injector.cs similarity index 97% rename from Tests/Injector.cs rename to Rx.Http.Tests/Injector.cs index 5aac097..3e05a9c 100644 --- a/Tests/Injector.cs +++ b/Rx.Http.Tests/Injector.cs @@ -3,7 +3,7 @@ using Rx.Http.Extensions; using Rx.Http.Logging; -namespace Tests +namespace Rx.Http.Tests { class Injector { diff --git a/Tests/NavigatorTests.cs b/Rx.Http.Tests/NavigatorTests.cs similarity index 99% rename from Tests/NavigatorTests.cs rename to Rx.Http.Tests/NavigatorTests.cs index 5606b0c..64c7c84 100644 --- a/Tests/NavigatorTests.cs +++ b/Rx.Http.Tests/NavigatorTests.cs @@ -9,7 +9,7 @@ using Rx.Http; using Xunit; -namespace Tests +namespace Rx.Http.Tests { public class NavigatorTests { diff --git a/Tests/PostmanEchoTests.cs b/Rx.Http.Tests/PostmanEchoTests.cs similarity index 99% rename from Tests/PostmanEchoTests.cs rename to Rx.Http.Tests/PostmanEchoTests.cs index 407f3e5..7bfbcd2 100644 --- a/Tests/PostmanEchoTests.cs +++ b/Rx.Http.Tests/PostmanEchoTests.cs @@ -11,7 +11,7 @@ using Xunit; using Rx.Http.Extensions; -namespace Tests +namespace Rx.Http.Tests { public class PostmanEchoTests { diff --git a/Tests/RequestTests.cs b/Rx.Http.Tests/RequestTests.cs similarity index 98% rename from Tests/RequestTests.cs rename to Rx.Http.Tests/RequestTests.cs index 35cffd5..a903282 100644 --- a/Tests/RequestTests.cs +++ b/Rx.Http.Tests/RequestTests.cs @@ -9,7 +9,7 @@ using Xunit; using System.IO; -namespace Tests +namespace Rx.Http.Tests { public class RequestTests { diff --git a/Rx.Http.Tests/Rx.Http.Tests.csproj b/Rx.Http.Tests/Rx.Http.Tests.csproj new file mode 100644 index 0000000..7e66dcf --- /dev/null +++ b/Rx.Http.Tests/Rx.Http.Tests.csproj @@ -0,0 +1,26 @@ + + + + net8.0 + false + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + \ No newline at end of file diff --git a/Rx.Http.sln b/Rx.Http.sln index 7e52513..7986b45 100644 --- a/Rx.Http.sln +++ b/Rx.Http.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.32014.148 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{7D26E97A-BA89-446C-BD25-363C9A047D6C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rx.Http.Tests", "Rx.Http.Tests\Rx.Http.Tests.csproj", "{7D26E97A-BA89-446C-BD25-363C9A047D6C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples", "Samples\Samples.csproj", "{4C43BBB8-042C-4623-A1ED-14A578B23AB3}" EndProject diff --git a/Rx.Http/Rx.Http.csproj b/Rx.Http/Rx.Http.csproj index 183f3b0..e3f43bd 100644 --- a/Rx.Http/Rx.Http.csproj +++ b/Rx.Http/Rx.Http.csproj @@ -1,15 +1,15 @@ - net6.0 - 2.0.3 - true - false - Lucas Simas - A lightweight library that is inpired in Angular Http Client built on top of .NET HttpClient that and help programmers to make asynchronous http requests. - https://github.com/lucassklp/Rx.Http - https://github.com/lucassklp/Rx.Http - rx.http.icon.png - LICENSE + net8.0 + 2.1.0 + true + false + Lucas Simas + A lightweight library that is inpired in Angular Http Client built on top of .NET HttpClient that and help programmers to make asynchronous http requests. + https://github.com/lucassklp/Rx.Http + https://github.com/lucassklp/Rx.Http + rx.http.icon.png + LICENSE diff --git a/Rx.Http/RxHttpClient.cs b/Rx.Http/RxHttpClient.cs index 93d3999..372dc3b 100644 --- a/Rx.Http/RxHttpClient.cs +++ b/Rx.Http/RxHttpClient.cs @@ -112,6 +112,46 @@ public IObservable Post(string url, Action options) return Request(url, options, HttpMethod.Post); } + public IObservable Patch(string url) + { + return Request(url, HttpMethod.Patch); + } + + public IObservable Patch(string url, object content) + { + return Request(url, content, HttpMethod.Patch); + } + + public IObservable Patch(string url, object content, Action options) + { + return Request(url, content, options, HttpMethod.Patch); + } + + public IObservable Patch(string url, Action options) + { + return Request(url, options, HttpMethod.Patch); + } + + public IObservable Patch(string url) + { + return Request(url, HttpMethod.Patch); + } + + public IObservable Patch(string url, object content) + { + return Request(url, content, HttpMethod.Patch); + } + + public IObservable Patch(string url, object content, Action options) + { + return Request(url, content, options, HttpMethod.Patch); + } + + public IObservable Patch(string url, Action options) + { + return Request(url, options, HttpMethod.Patch); + } + public IObservable Put(string url) { return Request(url, HttpMethod.Put); diff --git a/Rx.Http/RxHttpRequest.cs b/Rx.Http/RxHttpRequest.cs index 98862dd..145d794 100644 --- a/Rx.Http/RxHttpRequest.cs +++ b/Rx.Http/RxHttpRequest.cs @@ -3,6 +3,7 @@ using Rx.Http.MediaTypes.Abstractions; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net.Http; @@ -73,37 +74,66 @@ internal HttpContent BuildContent() #region Options - public override RxHttpRequestOptions AddHeader(string key, string value) + public override RxHttpRequestOptions AddHeader(string key, T value) { - Headers.Append(key, value); + Headers.Append(key, ConvertToString(value)); return this; } - public override RxHttpRequestOptions AddHeader(IEnumerable> pairs) + public override RxHttpRequestOptions AddHeader(string key, IEnumerable values) { - pairs.ToList().ForEach(x => AddHeader(x.Key, x.Value)); + foreach (var value in values) + { + AddHeader(key, value); + } + return this; + } + + public override RxHttpRequestOptions AddHeader(IEnumerable> pairs) + { + foreach (var item in pairs) + { + AddHeader(item.Key, item.Value); + } + return this; + } + + public override RxHttpRequestOptions AddHeader(IEnumerable>> pairs) + { + foreach (var pair in pairs) + { + foreach (var value in pair.Value) + { + AddHeader(pair.Key, value); + } + } + return this; } + public override RxHttpRequestOptions AddHeader(object obj) { AddHeader(obj.ToDictionary()); return this; } - public override RxHttpRequestOptions AddQueryString(string key, string value) + public override RxHttpRequestOptions AddQueryString(string key, T value) { - QueryStrings.Append(key, value); + QueryStrings.Append(key, ConvertToString(value)); return this; } - public override RxHttpRequestOptions AddQueryString(IEnumerable> pairs) + public override RxHttpRequestOptions AddQueryString(IEnumerable> pairs) { - pairs.ToList().ForEach(x => AddQueryString(x.Key, x.Value)); + foreach (var item in pairs) + { + AddQueryString(item.Key, item.Value); + } return this; } - public override RxHttpRequestOptions AddQueryString(IEnumerable>> pairs) + public override RxHttpRequestOptions AddQueryString(IEnumerable>> pairs) { foreach (var pair in pairs) { @@ -116,6 +146,15 @@ public override RxHttpRequestOptions AddQueryString(IEnumerable(string key, IEnumerable values) + { + foreach (var value in values) + { + AddQueryString(key, value); + } + return this; + } + public override RxHttpRequestOptions AddQueryString(object obj) { AddQueryString(obj.ToDictionary()); @@ -145,6 +184,26 @@ public override RxHttpRequestOptions SetResponseMediaType(IHttpMediaTypeDeserial this.ResponseMediaType = mediaType; return this; } + + private string ConvertToString(T value) + { + if(value is bool) + { + return value?.ToString()?.ToLower(); + } + + if(value is double asDouble) + { + return asDouble.ToString(CultureInfo.InvariantCulture); + } + + if(value is float asFloat) + { + return asFloat.ToString(CultureInfo.InvariantCulture); + } + + return value?.ToString(); + } #endregion } } \ No newline at end of file diff --git a/Rx.Http/RxHttpRequestOptions.cs b/Rx.Http/RxHttpRequestOptions.cs index 1018d8f..99052ba 100644 --- a/Rx.Http/RxHttpRequestOptions.cs +++ b/Rx.Http/RxHttpRequestOptions.cs @@ -14,17 +14,23 @@ public abstract class RxHttpRequestOptions public abstract RxHttpRequestOptions AddRequestInteceptor(RxRequestInterceptor interceptor); - public abstract RxHttpRequestOptions AddHeader(string key, string value); + public abstract RxHttpRequestOptions AddHeader(string key, T value); - public abstract RxHttpRequestOptions AddHeader(IEnumerable> pairs); + public abstract RxHttpRequestOptions AddHeader(string key, IEnumerable values); + + public abstract RxHttpRequestOptions AddHeader(IEnumerable> pairs); + + public abstract RxHttpRequestOptions AddHeader(IEnumerable>> pairs); public abstract RxHttpRequestOptions AddHeader(object obj); - public abstract RxHttpRequestOptions AddQueryString(string key, string value); + public abstract RxHttpRequestOptions AddQueryString(string key, T value); + + public abstract RxHttpRequestOptions AddQueryString(string key, IEnumerable values); - public abstract RxHttpRequestOptions AddQueryString(IEnumerable> pairs); + public abstract RxHttpRequestOptions AddQueryString(IEnumerable> pairs); - public abstract RxHttpRequestOptions AddQueryString(IEnumerable>> pairs); + public abstract RxHttpRequestOptions AddQueryString(IEnumerable>> pairs); public abstract RxHttpRequestOptions AddQueryString(object obj); diff --git a/Rx.Http/Serializers/NativeJsonSerializer.cs b/Rx.Http/Serializers/NativeJsonSerializer.cs index 84ddd4f..ca3ebb1 100644 --- a/Rx.Http/Serializers/NativeJsonSerializer.cs +++ b/Rx.Http/Serializers/NativeJsonSerializer.cs @@ -8,17 +8,15 @@ public class NativeJsonSerializer : ITwoWaysSerializable { public T Deserialize(Stream stream) { - StreamReader reader = new StreamReader(stream); - string text = reader.ReadToEnd(); - return JsonSerializer.Deserialize(text); + return JsonSerializer.Deserialize(stream); } public Stream Serialize(T data) where T : class { - var s = JsonSerializer.Serialize(data); + var json = JsonSerializer.Serialize(data); var stream = new MemoryStream(); var writer = new StreamWriter(stream); - writer.Write(s); + writer.Write(json); writer.Flush(); stream.Position = 0; return stream; diff --git a/Samples/Samples.csproj b/Samples/Samples.csproj index 133f0da..90457cc 100644 --- a/Samples/Samples.csproj +++ b/Samples/Samples.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 false diff --git a/Tests/ConsumersTests.cs b/Tests/ConsumersTests.cs index 9ff7e23..d26ed5f 100644 --- a/Tests/ConsumersTests.cs +++ b/Tests/ConsumersTests.cs @@ -1,5 +1,6 @@ using Models; using Models.Consumers; +using System; using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj deleted file mode 100644 index 61b5522..0000000 --- a/Tests/Tests.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - net6.0 - false - Tests - Tests - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - \ No newline at end of file