Skip to content

Commit 704f801

Browse files
committed
Added http service, response and filter
1 parent a9ca4eb commit 704f801

14 files changed

+370
-24
lines changed

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2023 radioActive DROID
3+
Copyright (c) 2023 Godwin peter .O
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Proton.Common.sln.DotSettings

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2-
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">// Copyright 2022 - $CURRENT_YEAR$ Godwin peter .O ([email protected])
3-
//
4-
// Licensed under the MIT License;
5-
// you may not use this file except in compliance with the License.
6-
// Unless required by applicable law or agreed to in writing, software
7-
// distributed under the License is distributed on an "AS IS" BASIS,
8-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9-
// See the License for the specific language governing permissions and
10-
// limitations under the License.</s:String></wpf:ResourceDictionary>
2+
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Copyright 2022 - $CURRENT_YEAR$ Godwin peter .O ([email protected])
3+
4+
Licensed under the MIT License;
5+
you may not use this file except in compliance with the License.
6+
Unless required by applicable law or agreed to in writing, software
7+
distributed under the License is distributed on an "AS IS" BASIS,
8+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the License for the specific language governing permissions and
10+
limitations under the License.</s:String></wpf:ResourceDictionary>

src/http/BaseHttpService.cs

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
using System.Net;
12+
using System.Net.Http.Json;
13+
using System.Text;
14+
using System.Text.Json;
15+
16+
namespace Proton.Common.Http;
17+
18+
public abstract class BaseHttpService(HttpClient http) {
19+
protected HttpRequestMessage CreateRequest(HttpMethod method, string uri, object? value = null) {
20+
var request = new HttpRequestMessage(method, uri);
21+
if (value != null)
22+
request.Content = new StringContent(JsonSerializer.Serialize(value), Encoding.UTF8, "application/json");
23+
return request;
24+
}
25+
26+
protected async Task SendRequest(HttpRequestMessage request) {
27+
await AddJwtHeader(request);
28+
try {
29+
using var response = await http.SendAsync(request);
30+
if (response.StatusCode == HttpStatusCode.Unauthorized) {
31+
await SignOut();
32+
return;
33+
}
34+
await HandleErrors(response);
35+
}
36+
catch (Exception) {
37+
Console.WriteLine("A HTTP callback error occurred");
38+
}
39+
}
40+
41+
protected async Task<T> SendRequest<T>(HttpRequestMessage request) {
42+
await AddJwtHeader(request);
43+
try {
44+
using var response = await http.SendAsync(request);
45+
if (response.StatusCode == HttpStatusCode.Unauthorized) {
46+
await SignOut();
47+
return default!;
48+
}
49+
await HandleErrors(response);
50+
var options = new JsonSerializerOptions {
51+
PropertyNameCaseInsensitive = true
52+
};
53+
options.Converters.Add(new Converters.StringConverter());
54+
55+
return (await response.Content.ReadFromJsonAsync<T>(options))!;
56+
}
57+
catch (Exception) {
58+
Console.WriteLine("A HTTP callback error occurred");
59+
}
60+
61+
return default!;
62+
}
63+
64+
protected abstract Task AddJwtHeader(HttpRequestMessage request);
65+
66+
protected abstract Task SignOut();
67+
68+
private async Task HandleErrors(HttpResponseMessage response) {
69+
if (!response.IsSuccessStatusCode) {
70+
var error = await response.Content.ReadFromJsonAsync<Dictionary<string, string>>();
71+
if (error != null) throw new Exception(error["message"]);
72+
}
73+
}
74+
}

src/http/Globals.cs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
global using System.Collections;

src/http/HttpService.cs

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
using Proton.Common.Extensions;
12+
using Proton.Common.Filters;
13+
14+
namespace Proton.Common.Http;
15+
16+
public abstract class HttpService (HttpClient http) : BaseHttpService(http), IHttpService {
17+
public async Task<T> Get<T>(string uri) {
18+
var request = new HttpRequestMessage(HttpMethod.Get, uri);
19+
return await SendRequest<T>(request);
20+
}
21+
22+
public async Task<T> Get<T>(string uri, object? query) {
23+
string queries = query != null ? query.GetQueryString() : (new PageFilter()).GetQueryString();
24+
var url = uri + queries;
25+
var request = new HttpRequestMessage(HttpMethod.Get, url);
26+
return await SendRequest<T>(request);
27+
}
28+
29+
public async Task Post(string uri, object? value) {
30+
var request = CreateRequest(HttpMethod.Post, uri, value);
31+
await SendRequest(request);
32+
}
33+
34+
public async Task<T> Post<T>(string uri) {
35+
var request = CreateRequest(HttpMethod.Post, uri);
36+
return await SendRequest<T>(request);
37+
}
38+
39+
public async Task<T> Post<T>(string uri, object? value) {
40+
var request = CreateRequest(HttpMethod.Post, uri, value);
41+
return await SendRequest<T>(request);
42+
}
43+
44+
public async Task Put(string uri, object? value) {
45+
var request = CreateRequest(HttpMethod.Put, uri, value);
46+
await SendRequest(request);
47+
}
48+
49+
public async Task<T> Put<T>(string uri) {
50+
var request = CreateRequest(HttpMethod.Put, uri);
51+
return await SendRequest<T>(request);
52+
}
53+
54+
public async Task<T> Put<T>(string uri, object? value) {
55+
var request = CreateRequest(HttpMethod.Put, uri, value);
56+
return await SendRequest<T>(request);
57+
}
58+
59+
public async Task Delete(string uri) {
60+
var request = CreateRequest(HttpMethod.Delete, uri);
61+
await SendRequest(request);
62+
}
63+
64+
public async Task<T> Delete<T>(string uri) {
65+
var request = CreateRequest(HttpMethod.Delete, uri);
66+
return await SendRequest<T>(request);
67+
}
68+
69+
public async Task<T> Delete<T>(string uri, ICollection? values) {
70+
var request = CreateRequest(HttpMethod.Delete, uri, values);
71+
return await SendRequest<T>(request);
72+
}
73+
}

src/http/HttpServiceExtensions.cs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
using Microsoft.Extensions.DependencyInjection;
12+
13+
namespace Proton.Common.Http;
14+
15+
public static class HttpServiceExtensions {
16+
public static IServiceCollection RegisterHttpServices(this IServiceCollection services) {
17+
18+
return services;
19+
}
20+
}

src/http/IHttpService.cs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
namespace Proton.Common.Http;
12+
13+
public interface IHttpService {
14+
Task<T> Get<T>(string uri);
15+
Task<T> Get<T>(string uri, object? query);
16+
Task Post(string uri, object? value);
17+
Task<T> Post<T>(string uri, object? value);
18+
Task<T> Post<T>(string uri);
19+
Task Put(string uri, object? value);
20+
Task<T> Put<T>(string uri);
21+
Task<T> Put<T>(string uri, object? value);
22+
Task Delete(string uri);
23+
Task<T> Delete<T>(string uri);
24+
Task<T> Delete<T>(string uri, ICollection? values);
25+
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
using System.Text.Json;
12+
using System.Text.Json.Serialization;
13+
14+
namespace Proton.Common.Converters;
15+
16+
public class StringConverter : JsonConverter<string> {
17+
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
18+
return reader.TokenType switch {
19+
JsonTokenType.Number => reader.GetInt32().ToString(),
20+
JsonTokenType.String => reader.GetString()!,
21+
_ => throw new JsonException()
22+
};
23+
}
24+
25+
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) {
26+
writer.WriteStringValue(value);
27+
}
28+
}

src/standard/Extensions/DateTimeExtensions.cs

+8-14
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,24 @@
1010

1111
namespace Proton.Common.Extensions {
1212
public static class DateTimeExtensions {
13-
public static TimeOnly ToTimeOnly(this DateTime dateTime) {
14-
return TimeOnly.FromDateTime(dateTime);
15-
}
13+
public static TimeOnly ToTimeOnly(this DateTime dateTime) => TimeOnly.FromDateTime(dateTime);
1614

17-
public static DateOnly ToDateOnly(this DateTime dateTime) {
18-
return DateOnly.FromDateTime(dateTime);
19-
}
15+
public static DateOnly ToDateOnly(this DateTime dateTime) => DateOnly.FromDateTime(dateTime);
16+
17+
public static DateTimeOffset Parse(this DateTimeOffset offset, DateTime time) => new(time, TimeSpan.Zero);
2018

2119
public static string TimeAgo(this DateTime dateTime) {
2220
string result;
2321
TimeSpan timeSpan = DateTime.Now.Subtract(dateTime);
2422

25-
if (timeSpan <= TimeSpan.FromSeconds(60)) {
23+
if (timeSpan <= TimeSpan.FromSeconds(60))
2624
result = $"{timeSpan.Seconds} seconds ago";
27-
}
28-
else if (timeSpan <= TimeSpan.FromMinutes(60)) {
25+
else if (timeSpan <= TimeSpan.FromMinutes(60))
2926
result = timeSpan.Minutes > 1 ? $"{timeSpan.Minutes} minutes ago" : "a minute ago";
30-
}
31-
else if (timeSpan <= TimeSpan.FromHours(24)) {
27+
else if (timeSpan <= TimeSpan.FromHours(24))
3228
result = timeSpan.Hours > 1 ? $"{timeSpan.Hours} hours ago" : "an hour ago";
33-
}
34-
else if (timeSpan <= TimeSpan.FromDays(30)) {
29+
else if (timeSpan <= TimeSpan.FromDays(30))
3530
result = timeSpan.Days > 1 ? $"{timeSpan.Days} days ago" : "yesterday";
36-
}
3731
else {
3832
result = timeSpan <= TimeSpan.FromDays(365)
3933
? timeSpan.Days > 30 ? $"{timeSpan.Days / 30} months ago" : "a month ago"

src/standard/Filters/DateFilter.cs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
namespace Proton.Common.Filters;
12+
13+
public class DateFilter : SearchFilter {
14+
public DateTimeOffset? StartDate { get; set; } = DateTimeOffset.Now.AddDays(-1);
15+
public DateTimeOffset? EndDate { get; set; } = DateTimeOffset.Now;
16+
}

src/standard/Filters/PageFilter.cs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
namespace Proton.Common.Filters;
12+
13+
public class PageFilter {
14+
public int Page { get; set; } = 1;
15+
public int PerPage { get; set; } = 25;
16+
public string SortBy { get; set; } = "Ascending";
17+
public string CombineWith { get; set; } = "Or";
18+
}

src/standard/Filters/SearchFilter.cs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2022 - 2023 Godwin peter .O ([email protected])
2+
//
3+
// Licensed under the MIT License;
4+
// you may not use this file except in compliance with the License.
5+
// Unless required by applicable law or agreed to in writing, software
6+
// distributed under the License is distributed on an "AS IS" BASIS,
7+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8+
// See the License for the specific language governing permissions and
9+
// limitations under the License.
10+
11+
namespace Proton.Common.Filters;
12+
13+
public class SearchFilter : PageFilter {
14+
public string? Search { get; set; }
15+
}

0 commit comments

Comments
 (0)