Skip to content

Commit

Permalink
Performance improvment - Reuse single HttpClient
Browse files Browse the repository at this point in the history
  • Loading branch information
maximn committed Oct 9, 2024
1 parent ec46889 commit 3743a77
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 22 deletions.
8 changes: 3 additions & 5 deletions GoogleMapsApi/Engine/MapsAPIGenericEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Threading.Tasks;
using System.Text;


namespace GoogleMapsApi.Engine
{
public delegate Uri UriCreatedDelegate(Uri uri);
Expand All @@ -21,7 +20,8 @@ public abstract class MapsAPIGenericEngine<TRequest, TResponse>
{
internal static event UriCreatedDelegate OnUriCreated;
internal static event RawResponseReceivedDelegate OnRawResponseReceived;
internal static TimeSpan DefaultTimeout = TimeSpan.FromSeconds(100);

private static readonly HttpClient client = new HttpClient();

protected internal static async Task<TResponse> QueryGoogleAPIAsync(TRequest request, TimeSpan timeout, CancellationToken token = default)
{
Expand All @@ -31,9 +31,7 @@ protected internal static async Task<TResponse> QueryGoogleAPIAsync(TRequest req
var requstUri = request.GetUri();
var uri = OnUriCreated?.Invoke(requstUri) ?? requstUri;

var client = new HttpClient();

var response = await client.DownloadDataTaskAsyncAsString(uri, timeout, token).ConfigureAwait(false);
var response = await client.DownloadDataTaskAsyncAsString(uri, timeout, token).ConfigureAwait(false);

OnRawResponseReceived?.Invoke(Encoding.UTF8.GetBytes(response));

Expand Down
38 changes: 21 additions & 17 deletions GoogleMapsApi/HttpClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ public static class HttpClientExtensions

public static async Task<string> DownloadDataTaskAsyncAsString(this HttpClient client, Uri address, TimeSpan timeout, CancellationToken token = new CancellationToken())
{
var dataDownloaded = await DownloadData(client, address, timeout, token).ConfigureAwait(false);

if (dataDownloaded != null)
return await dataDownloaded.Content.ReadAsStringAsync().ConfigureAwait(false);

return await GetCancelledTask<string>().ConfigureAwait(false);
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token))
{
cts.CancelAfter(timeout);

HttpResponseMessage response = await client.GetAsync(address, cts.Token).ConfigureAwait(false);
await HandleResponse(response, timeout);
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}

private static async Task<T> GetCancelledTask<T>()
Expand All @@ -70,24 +72,26 @@ private static async Task<T> GetCancelledTask<T>()
if (token.IsCancellationRequested)
return null;

client.Timeout = timeout;
var httpResponse = await client.GetAsync(address, token).ConfigureAwait(false);
await HandleResponse(httpResponse, timeout);
return httpResponse;
}

if (!httpResponse.IsSuccessStatusCode)
private static async Task HandleResponse(HttpResponseMessage response, TimeSpan timeout)
{
if (!response.IsSuccessStatusCode)
{
if (httpResponse.StatusCode == HttpStatusCode.Forbidden ||
httpResponse.StatusCode == HttpStatusCode.ProxyAuthenticationRequired ||
httpResponse.StatusCode == HttpStatusCode.Unauthorized)
throw new AuthenticationException(await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false));
if (response.StatusCode == HttpStatusCode.Forbidden ||
response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired ||
response.StatusCode == HttpStatusCode.Unauthorized)
throw new AuthenticationException(await response.Content.ReadAsStringAsync().ConfigureAwait(false));

if (httpResponse.StatusCode == HttpStatusCode.GatewayTimeout ||
httpResponse.StatusCode == HttpStatusCode.RequestTimeout)
if (response.StatusCode == HttpStatusCode.GatewayTimeout ||
response.StatusCode == HttpStatusCode.RequestTimeout)
throw new TimeoutException($"The request has exceeded the timeout limit of {timeout} and has been aborted.");

throw new HttpRequestException($"Failed with HttpResponse: {httpResponse.StatusCode} and message: {httpResponse.ReasonPhrase}");
throw new HttpRequestException($"Failed with HttpResponse: {response.StatusCode} and message: {response.ReasonPhrase}");
}

return httpResponse;
}
}
}

0 comments on commit 3743a77

Please sign in to comment.