Skip to content

Commit 40b2ce0

Browse files
authored
Merge pull request #4 from akrisanov/feat/add-patch-method-support
feat: Add PATCH Method Support to HttpClientAdapter and HttpClientWithCache
2 parents 440d71a + cf1aa85 commit 40b2ce0

7 files changed

Lines changed: 1383 additions & 58 deletions

File tree

src/Reliable.HttpClient.Caching/Abstractions/HttpCacheOptionsBuilder.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public HttpCacheOptionsBuilder AddHeader(string name, string value)
6363
{
6464
throw new ArgumentException($"'{nameof(name)}' cannot be null or whitespace.", nameof(name));
6565
}
66+
6667
ArgumentNullException.ThrowIfNull(value);
6768

6869
_options.DefaultHeaders[name] = value;
@@ -84,6 +85,7 @@ public HttpCacheOptionsBuilder AddHeaders(IDictionary<string, string> headers)
8485
{
8586
_options.DefaultHeaders[header.Key] = header.Value;
8687
}
88+
8789
return this;
8890
}
8991

src/Reliable.HttpClient.Caching/HttpClientWithCache.cs

Lines changed: 165 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,130 @@ public async Task<TResponse> PostAsync<TRequest, TResponse>(
164164
return await PostAsync<TRequest, TResponse>(requestUri.ToString(), content, headers, cancellationToken).ConfigureAwait(false);
165165
}
166166

167+
public async Task<HttpResponseMessage> PostAsync<TRequest>(
168+
string requestUri,
169+
TRequest content,
170+
CancellationToken cancellationToken = default)
171+
{
172+
HttpResponseMessage response = await _httpClient.PostAsJsonAsync(requestUri, content, cancellationToken).ConfigureAwait(false);
173+
174+
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
175+
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
176+
177+
return response;
178+
}
179+
180+
public async Task<HttpResponseMessage> PostAsync<TRequest>(
181+
string requestUri,
182+
TRequest content,
183+
IDictionary<string, string> headers,
184+
CancellationToken cancellationToken = default)
185+
{
186+
Dictionary<string, string> allHeaders = MergeHeaders(_cacheOptions.DefaultHeaders, headers);
187+
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Post, requestUri, allHeaders);
188+
request.Content = JsonContent.Create(content);
189+
190+
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
191+
192+
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
193+
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
194+
195+
return response;
196+
}
197+
198+
/// <inheritdoc />
199+
public async Task<TResponse> PatchAsync<TRequest, TResponse>(
200+
string requestUri,
201+
TRequest content,
202+
CancellationToken cancellationToken = default) where TResponse : class
203+
{
204+
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Patch, requestUri, _cacheOptions.DefaultHeaders);
205+
request.Content = JsonContent.Create(content);
206+
207+
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
208+
TResponse result = await _responseHandler.HandleAsync<TResponse>(response, cancellationToken).ConfigureAwait(false);
209+
210+
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
211+
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
212+
213+
return result;
214+
}
215+
216+
/// <inheritdoc />
217+
public async Task<TResponse> PatchAsync<TRequest, TResponse>(
218+
Uri requestUri,
219+
TRequest content,
220+
CancellationToken cancellationToken = default) where TResponse : class
221+
{
222+
return await PatchAsync<TRequest, TResponse>(requestUri.ToString(), content, cancellationToken).ConfigureAwait(false);
223+
}
224+
225+
/// <inheritdoc />
226+
public async Task<TResponse> PatchAsync<TRequest, TResponse>(
227+
string requestUri,
228+
TRequest content,
229+
IDictionary<string, string> headers,
230+
CancellationToken cancellationToken = default) where TResponse : class
231+
{
232+
Dictionary<string, string> allHeaders = MergeHeaders(_cacheOptions.DefaultHeaders, headers);
233+
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Patch, requestUri, allHeaders);
234+
request.Content = JsonContent.Create(content);
235+
236+
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
237+
TResponse result = await _responseHandler.HandleAsync<TResponse>(response, cancellationToken).ConfigureAwait(false);
238+
239+
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
240+
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
241+
242+
return result;
243+
}
244+
245+
/// <inheritdoc />
246+
public async Task<TResponse> PatchAsync<TRequest, TResponse>(
247+
Uri requestUri,
248+
TRequest content,
249+
IDictionary<string, string> headers,
250+
CancellationToken cancellationToken = default) where TResponse : class
251+
{
252+
return await PatchAsync<TRequest, TResponse>(requestUri.ToString(), content, headers, cancellationToken).ConfigureAwait(false);
253+
}
254+
255+
/// <inheritdoc />
256+
public async Task<HttpResponseMessage> PatchAsync<TRequest>(
257+
string requestUri,
258+
TRequest content,
259+
CancellationToken cancellationToken = default)
260+
{
261+
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Patch, requestUri, _cacheOptions.DefaultHeaders);
262+
request.Content = JsonContent.Create(content);
263+
264+
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
265+
266+
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
267+
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
268+
269+
return response;
270+
}
271+
272+
/// <inheritdoc />
273+
public async Task<HttpResponseMessage> PatchAsync<TRequest>(
274+
string requestUri,
275+
TRequest content,
276+
IDictionary<string, string> headers,
277+
CancellationToken cancellationToken = default)
278+
{
279+
Dictionary<string, string> allHeaders = MergeHeaders(_cacheOptions.DefaultHeaders, headers);
280+
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Patch, requestUri, allHeaders);
281+
request.Content = JsonContent.Create(content);
282+
283+
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
284+
285+
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
286+
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
287+
288+
return response;
289+
}
290+
167291
/// <inheritdoc />
168292
public async Task<TResponse> PutAsync<TRequest, TResponse>(
169293
string requestUri,
@@ -231,6 +355,34 @@ public async Task<TResponse> DeleteAsync<TResponse>(
231355
return result;
232356
}
233357

358+
public async Task<HttpResponseMessage> DeleteAsync(
359+
string requestUri,
360+
CancellationToken cancellationToken = default)
361+
{
362+
HttpResponseMessage response = await _httpClient.DeleteAsync(requestUri, cancellationToken).ConfigureAwait(false);
363+
364+
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
365+
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
366+
367+
return response;
368+
}
369+
370+
public async Task<HttpResponseMessage> DeleteAsync(
371+
string requestUri,
372+
IDictionary<string, string> headers,
373+
CancellationToken cancellationToken = default)
374+
{
375+
Dictionary<string, string> allHeaders = MergeHeaders(_cacheOptions.DefaultHeaders, headers);
376+
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Delete, requestUri, allHeaders);
377+
378+
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
379+
380+
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
381+
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
382+
383+
return response;
384+
}
385+
234386
/// <inheritdoc />
235387
public Task InvalidateCacheAsync(string pattern)
236388
{
@@ -339,31 +491,13 @@ Task<TResponse> IHttpClientAdapter.GetAsync<TResponse>(
339491
Uri requestUri, IDictionary<string, string> headers, CancellationToken cancellationToken) =>
340492
GetAsync<TResponse>(requestUri, headers, cacheDuration: null, cancellationToken);
341493

342-
async Task<HttpResponseMessage> IHttpClientAdapter.PostAsync<TRequest>(
343-
string requestUri, TRequest content, CancellationToken cancellationToken)
344-
{
345-
HttpResponseMessage response = await _httpClient.PostAsJsonAsync(requestUri, content, cancellationToken).ConfigureAwait(false);
346-
347-
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
348-
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
349-
350-
return response;
351-
}
352-
353-
async Task<HttpResponseMessage> IHttpClientAdapter.PostAsync<TRequest>(
354-
string requestUri, TRequest content, IDictionary<string, string> headers, CancellationToken cancellationToken)
355-
{
356-
Dictionary<string, string> allHeaders = MergeHeaders(_cacheOptions.DefaultHeaders, headers);
357-
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Post, requestUri, allHeaders);
358-
request.Content = JsonContent.Create(content);
359-
360-
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
361-
362-
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
363-
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
494+
Task<HttpResponseMessage> IHttpClientAdapter.PostAsync<TRequest>(
495+
string requestUri, TRequest content, CancellationToken cancellationToken) =>
496+
PostAsync(requestUri, content, cancellationToken);
364497

365-
return response;
366-
}
498+
Task<HttpResponseMessage> IHttpClientAdapter.PostAsync<TRequest>(
499+
string requestUri, TRequest content, IDictionary<string, string> headers, CancellationToken cancellationToken) =>
500+
PostAsync(requestUri, content, headers, cancellationToken);
367501

368502
Task<TResponse> IHttpClientAdapter.PostAsync<TRequest, TResponse>(
369503
string requestUri, TRequest content, CancellationToken cancellationToken) =>
@@ -381,35 +515,18 @@ Task<TResponse> IHttpClientAdapter.PutAsync<TRequest, TResponse>(
381515
string requestUri, TRequest content, IDictionary<string, string> headers, CancellationToken cancellationToken) =>
382516
PutAsync<TRequest, TResponse>(requestUri, content, headers, cancellationToken);
383517

384-
async Task<HttpResponseMessage> IHttpClientAdapter.DeleteAsync(string requestUri, CancellationToken cancellationToken)
385-
{
386-
HttpResponseMessage response = await _httpClient.DeleteAsync(requestUri, cancellationToken).ConfigureAwait(false);
387-
388-
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
389-
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
390-
391-
return response;
392-
}
393-
394-
async Task<HttpResponseMessage> IHttpClientAdapter.DeleteAsync(
395-
string requestUri, IDictionary<string, string> headers, CancellationToken cancellationToken)
396-
{
397-
Dictionary<string, string> allHeaders = MergeHeaders(_cacheOptions.DefaultHeaders, headers);
398-
using HttpRequestMessage request = CreateRequestWithHeaders(HttpMethod.Delete, requestUri, allHeaders);
399-
400-
HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
401-
402-
// Invalidate cache only after successful HTTP request (before response handler to maintain adapter contract)
403-
await InvalidateRelatedCacheAsync(requestUri).ConfigureAwait(false);
404-
405-
return response;
406-
}
407-
408518
Task<TResponse> IHttpClientAdapter.DeleteAsync<TResponse>(
409519
string requestUri, CancellationToken cancellationToken) =>
410520
DeleteAsync<TResponse>(requestUri, cancellationToken);
411521

412522
Task<TResponse> IHttpClientAdapter.DeleteAsync<TResponse>(
413523
string requestUri, IDictionary<string, string> headers, CancellationToken cancellationToken) =>
414524
DeleteAsync<TResponse>(requestUri, headers, cancellationToken);
525+
526+
Task<HttpResponseMessage> IHttpClientAdapter.DeleteAsync(string requestUri, CancellationToken cancellationToken) =>
527+
DeleteAsync(requestUri, cancellationToken);
528+
529+
Task<HttpResponseMessage> IHttpClientAdapter.DeleteAsync(
530+
string requestUri, IDictionary<string, string> headers, CancellationToken cancellationToken) =>
531+
DeleteAsync(requestUri, headers, cancellationToken);
415532
}

0 commit comments

Comments
 (0)