Skip to content

Commit

Permalink
fix: HttpClient instance per request
Browse files Browse the repository at this point in the history
  • Loading branch information
Patryk Plewa committed Feb 8, 2023
1 parent 040e8c1 commit 35187aa
Showing 1 changed file with 58 additions and 41 deletions.
99 changes: 58 additions & 41 deletions src/Crowdin.Api/CrowdinApiClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


using System;
using System.Collections.Generic;
using System.IO;
Expand Down Expand Up @@ -98,7 +98,7 @@ public class CrowdinApiClient : ICrowdinApiClient

private readonly string _baseUrl;
private readonly string _accessToken;
private readonly HttpClient _httpClient;
private readonly Func<HttpClient> _httpClientFactory;
private readonly IRetryService? _retryService;

private static readonly MediaTypeHeaderValue DefaultContentType = MediaTypeHeaderValue.Parse("application/json");
Expand All @@ -124,18 +124,16 @@ public class CrowdinApiClient : ICrowdinApiClient

public CrowdinApiClient(
CrowdinCredentials credentials,
HttpClient? httpClient = null,
Func<HttpClient>? httpClientFactory = null,
IJsonParser? jsonParser = null,
IRetryService? retryService = null)
{
_httpClient = httpClient ?? new HttpClient();
_httpClientFactory = httpClientFactory ?? (() => new HttpClient());
DefaultJsonParser = jsonParser ?? new JsonParser(DefaultJsonSerializerOptions);
_retryService = retryService;

_accessToken = credentials.AccessToken;
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", credentials.AccessToken);


// pass base url full
if (!string.IsNullOrWhiteSpace(credentials.BaseUrl))
{
Expand Down Expand Up @@ -180,69 +178,79 @@ public class CrowdinApiClient : ICrowdinApiClient

public Task<CrowdinApiResult> SendGetRequest(string subUrl, IDictionary<string, string>? queryParams = null)
{
var request = new HttpRequestMessage
Func<HttpRequestMessage> requestFn = () => new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(FormRequestUrl(subUrl, queryParams))
};

return SendRequest(request);
return SendRequest(requestFn);
}

public Task<CrowdinApiResult> SendPostRequest(
string subUrl, object? body = null,
IDictionary<string, string>? extraHeaders = null)
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(FormRequestUrl(subUrl))
};

if (body != null)
Func<HttpRequestMessage> requestFn = () =>
{
request.Content = CreateJsonContent(body);
}
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(FormRequestUrl(subUrl))
};
if (extraHeaders != null && extraHeaders.Count > 0)
{
foreach (KeyValuePair<string, string> kvp in extraHeaders)
if (body != null)
{
request.Headers.Add(kvp.Key, kvp.Value);
request.Content = CreateJsonContent(body);
}
if (extraHeaders != null && extraHeaders.Count > 0)
{
foreach (KeyValuePair<string, string> kvp in extraHeaders)
{
request.Headers.Add(kvp.Key, kvp.Value);
}
}
}
return SendRequest(request);
return request;
};

return SendRequest(requestFn);
}

public Task<CrowdinApiResult> SendPutRequest(string subUrl, object? body = null)
{
var request = new HttpRequestMessage
Func<HttpRequestMessage> requestFn = () =>
{
Method = HttpMethod.Put,
RequestUri = new Uri(FormRequestUrl(subUrl))
};
var request = new HttpRequestMessage
{
Method = HttpMethod.Put,
RequestUri = new Uri(FormRequestUrl(subUrl))
};
if (body != null)
{
request.Content = CreateJsonContent(body);
}
if (body != null)
{
request.Content = CreateJsonContent(body);
}
return SendRequest(request);
return request;
};

return SendRequest(requestFn);
}

public Task<CrowdinApiResult> SendPatchRequest(
string subUrl, IEnumerable<PatchEntry> body,
IDictionary<string, string>? queryParams = null)
{
var request = new HttpRequestMessage
Func<HttpRequestMessage> requestFn = () => new HttpRequestMessage
{
Method = new HttpMethod("PATCH"),
Content = CreateJsonContent(body),
RequestUri = new Uri(FormRequestUrl(subUrl, queryParams))
};

return SendRequest(request);
return SendRequest(requestFn);
}

public Task<HttpStatusCode> SendDeleteRequest(string subUrl, IDictionary<string, string>? queryParams = null)
Expand All @@ -258,7 +266,7 @@ public Task<CrowdinApiResult> SendDeleteRequest_FullResult(string subUrl, IDicti
RequestUri = new Uri(FormRequestUrl(subUrl, queryParams))
};

return SendRequest(request);
return SendRequest(() => request);
}

public Task<CrowdinApiResult> UploadFile(string subUrl, string filename, Stream fileStream)
Expand All @@ -272,7 +280,7 @@ public Task<CrowdinApiResult> UploadFile(string subUrl, string filename, Stream
request.Headers.Add("Crowdin-API-FileName", filename);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

return SendRequest(request);
return SendRequest(() => request);
}

public static async Task<T[]> WithFetchAll<T>(
Expand Down Expand Up @@ -308,14 +316,23 @@ public Task<CrowdinApiResult> UploadFile(string subUrl, string filename, Stream
return outResultList.ToArray();
}

private async Task<CrowdinApiResult> SendRequest(HttpRequestMessage request)
private HttpClient GetHttpClientInstance()
{
var httpClient = _httpClientFactory();
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", _accessToken);

return httpClient;
}

private async Task<CrowdinApiResult> SendRequest(Func<HttpRequestMessage> requestFn)
{
var result = new CrowdinApiResult();

HttpResponseMessage response =
_retryService != null
? await _retryService.ExecuteRequestAsync(() => _httpClient.SendAsync(request))
: await _httpClient.SendAsync(request);
? await _retryService.ExecuteRequestAsync(() => GetHttpClientInstance().SendAsync(requestFn()))
: await GetHttpClientInstance().SendAsync(requestFn());

await CheckDefaultPreconditionsAndErrors(response);
result.StatusCode = response.StatusCode;
Expand Down

0 comments on commit 35187aa

Please sign in to comment.