11using System . Net ;
2+ using System . Net . Http . Headers ;
23using System . Net . Http . Json ;
34using System . Text ;
45using System . Text . Json ;
@@ -13,16 +14,55 @@ namespace TeamUp.ApiLayer;
1314public sealed partial class ApiClient
1415{
1516 private readonly HttpClient _client ;
17+ private readonly IAuthService _authService ;
1618
17- public ApiClient ( HttpClient client )
19+ public ApiClient ( HttpClient client , IAuthService authService )
1820 {
1921 _client = client ;
22+ _authService = authService ;
23+ }
24+
25+ private Task < Result > SendAsync ( HttpMethod method , string uri , CancellationToken ct ) => SendAsync ( method , uri , null , ct ) ;
26+
27+ private Task < Result > SendAsync ( HttpMethod method , string uri , Action < HttpRequestMessage > ? configure , CancellationToken ct )
28+ {
29+ var request = new HttpRequestMessage
30+ {
31+ Method = method ,
32+ RequestUri = new Uri ( uri , UriKind . Relative ) ,
33+ } ;
34+
35+ if ( configure is not null )
36+ {
37+ configure ( request ) ;
38+ }
39+
40+ return SendRequestAsync ( request , ct ) ;
41+ }
42+
43+ private Task < Result < TResponse > > SendAsync < TResponse > ( HttpMethod method , string uri , CancellationToken ct ) =>
44+ SendAsync < TResponse > ( method , uri , null , ct ) ;
45+
46+ private Task < Result < TResponse > > SendAsync < TResponse > ( HttpMethod method , string uri , Action < HttpRequestMessage > ? configure , CancellationToken ct )
47+ {
48+ var request = new HttpRequestMessage
49+ {
50+ Method = method ,
51+ RequestUri = new Uri ( uri , UriKind . Relative ) ,
52+ } ;
53+
54+ if ( configure is not null )
55+ {
56+ configure ( request ) ;
57+ }
58+
59+ return SendRequestAsync < TResponse > ( request , ct ) ;
2060 }
2161
2262 private Task < Result < TResponse > > SendAsync < TRequest , TResponse > ( HttpMethod method , string uri , TRequest payload , CancellationToken ct ) =>
2363 SendAsync < TRequest , TResponse > ( method , uri , payload , null , ct ) ;
2464
25- private async Task < Result < TResponse > > SendAsync < TRequest , TResponse > ( HttpMethod method , string uri , TRequest payload , Action < HttpRequestMessage > ? configure , CancellationToken ct )
65+ private async Task < Result < TResponse > > SendAsync < TRequest , TResponse > ( HttpMethod method , string uri , TRequest ? payload , Action < HttpRequestMessage > ? configure , CancellationToken ct )
2666 {
2767 var json = JsonSerializer . Serialize ( payload ) ;
2868 var request = new HttpRequestMessage
@@ -37,38 +77,79 @@ private async Task<Result<TResponse>> SendAsync<TRequest, TResponse>(HttpMethod
3777 configure ( request ) ;
3878 }
3979
80+ return await SendRequestAsync < TResponse > ( request , ct ) ;
81+ }
82+
83+ private async Task < Result > SendRequestAsync ( HttpRequestMessage request , CancellationToken ct )
84+ {
85+ await InjectAuthToken ( request , ct ) ;
86+
87+ var response = await _client . SendAsync ( request , ct ) ;
88+
89+ if ( ! response . IsSuccessStatusCode )
90+ {
91+ return await ParseErrorResponse ( response , ct ) ;
92+ }
93+
94+ return Result . Success ;
95+ }
96+
97+ private async Task < Result < TResponse > > SendRequestAsync < TResponse > ( HttpRequestMessage request , CancellationToken ct )
98+ {
99+ await InjectAuthToken ( request , ct ) ;
100+
40101 var response = await _client . SendAsync ( request , ct ) ;
41102
42103 if ( ! response . IsSuccessStatusCode )
43104 {
44- if ( response . StatusCode == HttpStatusCode . Unauthorized )
45- {
46- //logout
47- }
48-
49- var contentType = response . Content . Headers . ContentType ? . MediaType ;
50- if ( contentType != "application/problem+json" )
51- {
52- return new ApiError ( "Api.UnexpectedError" , $ "Unexpected response with content type '{ contentType } '.", response . StatusCode ) ;
53- }
54-
55- var problemDetails = await response . Content . ReadFromJsonAsync < ValidationProblemDetails > ( ct ) ;
56- if ( problemDetails is null )
57- {
58- return new ApiError ( "Api.SerializationError" , "Failed to deserialize error response." , response . StatusCode ) ;
59- }
60-
61- var title = problemDetails . Title ?? "Undefined Title" ;
62- var detail = problemDetails . Detail ?? "Undefined Detail" ;
63-
64- if ( problemDetails . Errors . Count > 0 )
65- {
66- return new ApiValidationError ( "Api.ValidationError" , "One or more validation errors occurred." , problemDetails . Errors ) ;
67- }
68-
69- return new ApiError ( "Api.Error" , detail , response . StatusCode ) ;
105+ return await ParseErrorResponse ( response , ct ) ;
106+ }
107+
108+ var responsePayload = await response . Content . ReadFromJsonAsync < TResponse > ( ct ) ;
109+ if ( responsePayload is null )
110+ {
111+ return new ApiError ( "Api.SerializationError" , "Failed to deserialize response." , response . StatusCode ) ;
112+ }
113+
114+ return responsePayload ;
115+ }
116+
117+ private async Task < Error > ParseErrorResponse ( HttpResponseMessage response , CancellationToken ct )
118+ {
119+ if ( response . StatusCode == HttpStatusCode . Unauthorized )
120+ {
121+ await _authService . LogoutAsync ( ct : ct ) ;
122+ }
123+
124+ var contentType = response . Content . Headers . ContentType ? . MediaType ;
125+ if ( contentType != "application/problem+json" )
126+ {
127+ return new ApiError ( "Api.UnexpectedError" , $ "Unexpected response with content type '{ contentType } '.", response . StatusCode ) ;
70128 }
71129
72- return await response . Content . ReadFromJsonAsync < TResponse > ( ct ) ;
130+ var problemDetails = await response . Content . ReadFromJsonAsync < ValidationProblemDetails > ( ct ) ;
131+ if ( problemDetails is null )
132+ {
133+ return new ApiError ( "Api.SerializationError" , "Failed to deserialize error response." , response . StatusCode ) ;
134+ }
135+
136+ var title = problemDetails . Title ?? "Undefined Title" ;
137+ var detail = problemDetails . Detail ?? "Undefined Detail" ;
138+
139+ if ( problemDetails . Errors . Count > 0 )
140+ {
141+ return new ApiValidationError ( "Api.ValidationError" , "One or more validation errors occurred." , problemDetails . Errors ) ;
142+ }
143+
144+ return new ApiError ( "Api.Error" , detail , response . StatusCode ) ;
145+ }
146+
147+ private async Task InjectAuthToken ( HttpRequestMessage request , CancellationToken ct )
148+ {
149+ var jwt = await _authService . GetTokenAsync ( ct ) ;
150+ if ( jwt is not null )
151+ {
152+ request . Headers . Authorization = new AuthenticationHeaderValue ( "Bearer" , jwt ) ;
153+ }
73154 }
74155}
0 commit comments