Skip to content

Commit bad4ed2

Browse files
chore : (RequestBuilder) Adding support for versioned api
1 parent 9490055 commit bad4ed2

File tree

11 files changed

+119
-35
lines changed

11 files changed

+119
-35
lines changed

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,15 @@
1818

1919
### 🐛 Bug Fixes
2020

21-
- Fixed a bug where the entire query string was encoded instead of only the query parameter keys and values.
21+
- Fixed a bug where the entire query string was encoded instead of only the query parameter keys and values.
22+
23+
## 2.1.0
24+
25+
### ✨ Features
26+
27+
- Added support for Versioned API routes via `VersionedEndpoint` class, and `GetBuilder(VersionedEndpoint endpoint)` method signatures.
28+
- Added support for M2M authentication via M2MAuthenticationClient.
29+
30+
### 🛠 Technical
31+
32+
- Overriding `GetBuilder` now changes the behaviour of `GetBuilderAsync`.

NotoriousClient.Sample/Program.cs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
// See https://aka.ms/new-console-template for more information
22

33
using Microsoft.Extensions.DependencyInjection;
4+
45
using NotoriousClient.Builder;
5-
using NotoriousClient.Builder.Authentication;
66
using NotoriousClient.Clients;
7-
using NotoriousClient.Converters;
87
using NotoriousClient.Sender;
98

109
Console.WriteLine("Hello, World!");
@@ -36,9 +35,8 @@ public class User
3635
}
3736
public class UserClient : BaseClient
3837
{
39-
private Endpoint GET_USERS_ENDPOINT = new Endpoint("/api/users", Method.Get);
40-
private Endpoint GET_USER_ENDPOINT = new Endpoint("/api/users/{id}", Method.Get);
41-
private Endpoint CREATE_USER_ENDPOINT = new Endpoint("/api/users", Method.Post);
38+
private Endpoint GET_USERS_ENDPOINT = new Endpoint("/users", Method.Get);
39+
private VersionedEndpoint CREATE_USER_ENDPOINT = new VersionedEndpoint("/users", Method.Post, "v1.0");
4240
public UserClient(IRequestSender sender, string url) : base(sender, url)
4341
{
4442
}
@@ -55,18 +53,6 @@ public async Task<IEnumerable<User>> GetUsers()
5553
return response.ReadAs<IEnumerable<User>>();
5654
}
5755

58-
public async Task<IEnumerable<User>> GetUser(int id)
59-
{
60-
HttpRequestMessage request = GetBuilder(GET_USERS_ENDPOINT)
61-
.WithAuthentication("username", "password")
62-
.AddEndpointParameter("id", id.ToString())
63-
.Build();
64-
65-
HttpResponseMessage response = await Sender.SendAsync(request);
66-
67-
return response.ReadAs<IEnumerable<User>>();
68-
}
69-
7056
public async Task<IEnumerable<User>> CreateUser(User user)
7157
{
7258
HttpRequestMessage request = GetBuilder(CREATE_USER_ENDPOINT)
@@ -94,7 +80,7 @@ public TotoBuilder(string url, string route, Method method) : base(url, route, m
9480

9581
public override HttpRequestMessage Build()
9682
{
97-
HttpRequestMessage request = base.Build();
83+
HttpRequestMessage request = base.Build();
9884
request.Headers.Add("TOTO", toto);
9985
return request;
10086
}

NotoriousClient.Tests.Unit/RequestBuilderURIUnitTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,22 @@ public void RequestBuilder_Should_AddUrlSlashProperly()
5353
Assert.NotNull(request.RequestUri);
5454
Assert.Equal("https://toto.com/pandas", request.RequestUri.AbsoluteUri);
5555
}
56+
57+
[GWTFact(given: "a url, an endpoint, an HTTP Verb and a version",
58+
when: "i build a request",
59+
then: "request has right url, endpoint, verb, and version")]
60+
public void RequestBuilder_Should_HandleVersionProperly()
61+
{
62+
string url = "https://toto.com/api";
63+
VersionedEndpoint endpoint = new VersionedEndpoint("pandas", Method.Get, "v1.0");
64+
65+
RequestBuilder requestBuilder = new RequestBuilder(url, endpoint);
66+
HttpRequestMessage request = requestBuilder.Build();
67+
68+
Assert.Equal(HttpMethod.Get, request.Method);
69+
Assert.NotNull(request.RequestUri);
70+
Assert.Equal("https://toto.com/api/v1.0/pandas", request.RequestUri.AbsoluteUri);
71+
}
5672
#endregion
5773

5874
#region QueryParams

NotoriousClient.slnx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Solution>
2+
<Folder Name="/CI/">
3+
<File Path=".github/workflows/prerelease.yml" />
4+
<File Path=".github/workflows/release.yml" />
5+
</Folder>
6+
<Folder Name="/Docs/">
7+
<File Path="CHANGELOG.md" />
8+
<File Path="LICENSE.txt" />
9+
<File Path="README.md" />
10+
</Folder>
11+
<Project Path="NotoriousClient.Sample/NotoriousClient.Sample.csproj" />
12+
<Project Path="NotoriousClient.Tests.Unit/NotoriousClient.Tests.Unit.csproj" />
13+
<Project Path="NotoriousClient/NotoriousClient.csproj" />
14+
</Solution>

NotoriousClient/Builder/RequestBuilder.Uri.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ public partial class RequestBuilder : IRequestBuilder
44
{
55
private string _url;
66
private string _route;
7+
private string? _version;
78
private Dictionary<string, string> _queryParams = new Dictionary<string, string>();
89
private Dictionary<string, string> _endpointParams = new Dictionary<string, string>();
910
private const char START_ENDPOINT_PARAM = '{';
@@ -113,9 +114,10 @@ private string GetReplacementToken(string key)
113114
private string GetUri()
114115
{
115116
var url = !_url.EndsWith("/") ? _url : _url.Substring(0, _url.Length - 1);
117+
var version = !string.IsNullOrEmpty(_version) ? $"/{_version}" : string.Empty;
116118
var endpoint = _route.StartsWith("/") ? _route : $"/{_route}";
117119

118-
return url + endpoint;
120+
return url + version + endpoint;
119121
}
120122
#endregion
121123
}

NotoriousClient/Builder/RequestBuilder.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
///<inheritdoc/>
44
public partial class RequestBuilder : IRequestBuilder
55
{
6-
private Method _method;
7-
6+
private Method _method;
7+
88
/// <summary>
99
/// Initialize a new instance of <see cref="RequestBuilder"/>.
1010
/// </summary>
@@ -20,14 +20,28 @@ public RequestBuilder(string url, string route, Method method)
2020
/// <summary>
2121
/// Initialize a new instance of <see cref="RequestBuilder"/>.
2222
/// </summary>
23-
public RequestBuilder(string url, Endpoint endpoint)
23+
public RequestBuilder(string url, Endpoint endpoint) : this(url, endpoint.Route, endpoint.Method)
2424
{
25-
if (string.IsNullOrEmpty(url)) throw new ArgumentNullException();
26-
ArgumentNullException.ThrowIfNull(endpoint, nameof(endpoint));
25+
}
2726

27+
/// <summary>
28+
/// Initialize a new instance of <see cref="RequestBuilder"/>.
29+
/// </summary>
30+
public RequestBuilder(string url, string route, string? version, Method method)
31+
{
32+
if (string.IsNullOrEmpty(url)) throw new ArgumentNullException();
33+
if (string.IsNullOrEmpty(route)) throw new ArgumentNullException();
2834
_url = url;
29-
_route = endpoint.Route;
30-
_method = endpoint.Method;
35+
_route = route;
36+
_method = method;
37+
_version = version;
38+
}
39+
40+
/// <summary>
41+
/// Initialize a new instance of <see cref="RequestBuilder"/>.
42+
/// </summary>
43+
public RequestBuilder(string url, VersionedEndpoint endpoint) : this(url, endpoint.Route, endpoint.Version, endpoint.Method)
44+
{
3145
}
3246

3347
///<inheritdoc/>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace NotoriousClient.Builder
2+
{
3+
public class VersionedEndpoint : Endpoint
4+
{
5+
public string Version { get; set; }
6+
public VersionedEndpoint(string route, Method method, string version) : base(route, method)
7+
{
8+
Version = version;
9+
}
10+
}
11+
}

NotoriousClient/Clients/BaseClient.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public abstract class BaseClient
1616
protected IRequestSender Sender { get; }
1717

1818
/// <summary>
19-
/// Initialize a new instance of <see cref="SynchronousBaseClient"/>.
19+
/// Initialize a new instance of <see cref="BaseClient"/>.
2020
/// </summary>
2121
/// <param name="sender">Class used to send <see cref="HttpRequestMessage"/>.</param>
2222
/// <param name="url">Base URL of api (ex: https://myapi.com/).</param>
@@ -34,8 +34,8 @@ protected BaseClient(IRequestSender sender, string url)
3434
/// </summary>
3535
/// <param name="route">Request's Route.</param>
3636
/// <param name="method">Request's Method (GET, POST, PUT, DELETE...).</param>
37-
protected virtual IRequestBuilder GetBuilder(string route, Method method = Method.Get)
38-
=> new RequestBuilder(_url, route, method);
37+
protected virtual IRequestBuilder GetBuilder(string route, Method method = Method.Get, string? version = null)
38+
=> new RequestBuilder(_url, route, version, method);
3939

4040
/// <summary>
4141
/// Get preconfigured <see cref="IRequestBuilder"/>.
@@ -44,19 +44,33 @@ protected virtual IRequestBuilder GetBuilder(string route, Method method = Metho
4444
protected IRequestBuilder GetBuilder(Endpoint endpoint)
4545
=> GetBuilder(endpoint.Route, endpoint.Method);
4646

47+
/// <summary>
48+
/// Get preconfigured <see cref="IRequestBuilder"/> with versioning.
49+
/// </summary>
50+
/// <param name="endpoint">Request's <see cref="Endpoint"/>.</param>
51+
protected IRequestBuilder GetBuilder(VersionedEndpoint endpoint)
52+
=> GetBuilder(endpoint.Route, endpoint.Method, endpoint.Version);
53+
4754
/// <summary>
4855
/// Get preconfigured <see cref="IRequestBuilder"/>.
4956
/// </summary>
5057
/// <param name="route">Request's Route.</param>
5158
/// <param name="method">Request's Method (GET, POST, PUT, DELETE...).</param>
52-
protected virtual async Task<IRequestBuilder> GetBuilderAsync(string route, Method method = Method.Get)
53-
=> new RequestBuilder(_url, route, method);
59+
protected virtual async Task<IRequestBuilder> GetBuilderAsync(string route, Method method = Method.Get, string? version = null)
60+
=> GetBuilder(route, method, version);
5461

5562
/// <summary>
5663
/// Get preconfigured <see cref="IRequestBuilder"/>.
5764
/// </summary>
5865
/// <param name="endpoint">Request's <see cref="Endpoint"/>.</param>
5966
protected Task<IRequestBuilder> GetBuilderAsync(Endpoint endpoint)
6067
=> GetBuilderAsync(endpoint.Route, endpoint.Method);
68+
69+
/// <summary>
70+
/// Get preconfigured <see cref="IRequestBuilder"/> with versioning.
71+
/// </summary>
72+
/// <param name="endpoint">Request's <see cref="VersionedEndpoint"/>.</param>
73+
protected Task<IRequestBuilder> GetBuilderAsync(VersionedEndpoint endpoint)
74+
=> GetBuilderAsync(endpoint.Route, endpoint.Method, endpoint.Version);
6175
}
6276
}

NotoriousClient/Clients/BasicAuthBaseClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ protected BasicAuthBaseClient(IRequestSender sender, string url, string login, s
3333
/// </summary>
3434
/// <param name="route">Request's Route.</param>
3535
/// <param name="method">Request's method (GET, POST, PUT, DELETE...).</param>
36-
protected override IRequestBuilder GetBuilder(string route, Method method = Method.Get)
36+
protected override IRequestBuilder GetBuilder(string route, Method method = Method.Get, string? version = null)
3737
=> base.GetBuilder(route, method).WithAuthentication(_login, _password);
3838
}
3939
}

NotoriousClient/NotoriousClient.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>net8.0</TargetFramework>
3+
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
44
<Description>A fluent HTTPResponseMessage builder with fully extendable API Client implementation.</Description>
55
<PackageId>NotoriousClient</PackageId>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
8-
<VersionPrefix>2.0.2</VersionPrefix>
8+
<VersionPrefix>2.1.0</VersionPrefix>
99
<PackageReadmeFile>README.md</PackageReadmeFile>
1010
<Authors>Brice SCHUMACHER</Authors>
1111
<RepositoryUrl>https://github.com/Notorious-Coding/Notorious-Client/</RepositoryUrl>

0 commit comments

Comments
 (0)