Skip to content

Commit

Permalink
Merge pull request #86 from atidev/BILL-135097
Browse files Browse the repository at this point in the history
BILL-134487, httpclient extensions which uses newtonsoft json serializer
  • Loading branch information
alan-kh authored Jul 25, 2024
2 parents 2d1cf2c + cbafac3 commit 8615548
Show file tree
Hide file tree
Showing 5 changed files with 352 additions and 10 deletions.
2 changes: 1 addition & 1 deletion ATI.Services.Common/ATI.Services.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<PackageReference Include="NLog" Version="4.7.6" />
<PackageReference Include="NLog.DiagnosticSource" Version="1.3.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
<PackageReference Include="Npgsql" Version="7.0.6" />
<PackageReference Include="Npgsql" Version="8.0.3" />
<PackageReference Include="Polly" Version="7.2.4" />
<PackageReference Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" />
<PackageReference Include="prometheus-net" Version="8.2.1" />
Expand Down
6 changes: 3 additions & 3 deletions ATI.Services.Common/Behaviors/OperationResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ public OperationResult(OperationResult operationResult)
Exception = operationResult.Exception;
}

public OperationResult(Exception exception)
public OperationResult(Exception exception, string message = null)
{
ActionStatus = ActionStatus.InternalServerError;
Errors.Add(new OperationError(ActionStatus, exception.Message));
Errors.Add(new OperationError(ActionStatus, message ?? exception.Message));
Exception = exception;
}

Expand Down Expand Up @@ -240,7 +240,7 @@ public OperationResult(OperationError operationError, Dictionary<string, object>
{
}

public OperationResult(Exception exception) : base(exception)
public OperationResult(Exception exception, string message = null) : base(exception)
{ }
}
}
3 changes: 1 addition & 2 deletions ATI.Services.Common/Http/Extensions/HttpClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,7 @@ public static async Task<OperationResult<string>> GetStringAsync(this HttpClient
string url,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializerOptions serializerOptions = null,
Dictionary<string, string> headers = null,
RetryPolicySettings retryPolicySettings = null)
{
try
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,345 @@
using System.Collections.Generic;
using System.Net.Http;
using ATI.Services.Common.Behaviors;
using ATI.Services.Common.Policies;
using System.Threading.Tasks;
using NLog;
using JetBrains.Annotations;
using Newtonsoft.Json;
using ATI.Services.Common.Logging;
using Newtonsoft.Json.Serialization;
using System;
using System.IO;
using ATI.Services.Common.Extensions;
using System.Text;

namespace ATI.Services.Common.Http.Extensions.Newtonsoft;

[Obsolete("Хотят оставить только System.Text.Json в этой библиотеке")]
public static class HttpClientExtensionsForNewtonsoft
{
private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
private static readonly JsonSerializer SnakeCaseSerializer = new()
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy {
ProcessDictionaryKeys = true,
OverrideSpecifiedNames = true
}
}
};

#region Базовые методы

[PublicAPI]
public static async Task<OperationResult<TResponse>> SendAsync<TResponse>(
this HttpClient httpClient,
HttpMethod httpMethod,
string url,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null,
ILogger logger = null,
bool checkResponseStatusCode = true
)
{
try
{
logger ??= Logger;
serializer ??= SnakeCaseSerializer;

using var requestMessage
= HttpClientExtensions.CreateHttpRequestMessageAndSetBaseFields(httpMethod, url, metricEntity, urlTemplate, headers, retryPolicySettings);

using var responseMessage = await httpClient.SendAsync(requestMessage);

if (checkResponseStatusCode && !responseMessage.IsSuccessStatusCode)
return new OperationResult<TResponse>(responseMessage.StatusCode);

await using var stream = await responseMessage.Content.ReadAsStreamAsync();
using var reader = new StreamReader(stream);
using var jsonReader = new JsonTextReader(reader);
var response = serializer.Deserialize<TResponse>(jsonReader);

return new OperationResult<TResponse>(response, OperationResult.GetActionStatusByHttpStatusCode(responseMessage.StatusCode));
}
catch (Exception ex)
{
logger.ErrorWithObject(ex, new { httpMethod, url, headers });

return new OperationResult<TResponse>(ex);
}
}

[PublicAPI]
public static async Task<OperationResult<TResponse>> SendAsync<TRequest, TResponse>(
this HttpClient httpClient,
HttpMethod httpMethod,
string url,
TRequest request,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null,
ILogger logger = null,
bool checkResponseStatusCode = true
)
{
try
{
logger ??= Logger;
serializer ??= SnakeCaseSerializer;

using var requestMessage =
HttpClientExtensions.CreateHttpRequestMessageAndSetBaseFields(httpMethod, url, metricEntity, urlTemplate, headers, retryPolicySettings);

var content = request != null ? serializer.Serialize(request) : string.Empty;
requestMessage.Content = new StringContent(content, Encoding.UTF8, "application/json");

using var responseMessage = await httpClient.SendAsync(requestMessage);

if (checkResponseStatusCode && !responseMessage.IsSuccessStatusCode)
return new OperationResult<TResponse>(responseMessage.StatusCode);

await using var stream = await responseMessage.Content.ReadAsStreamAsync();
using var reader = new StreamReader(stream);
using var jsonReader = new JsonTextReader(reader);
var response = serializer.Deserialize<TResponse>(jsonReader);

return new OperationResult<TResponse>(response, OperationResult.GetActionStatusByHttpStatusCode(responseMessage.StatusCode));
}
catch (Exception ex)
{
logger.ErrorWithObject(ex, new { httpMethod, url, request, headers });

return new OperationResult<TResponse>(ex);
}
}

[PublicAPI]
public static async Task<OperationResult<string>> SendAsync<TRequest>(
this HttpClient httpClient,
HttpMethod httpMethod,
string url,
TRequest request,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null,
ILogger logger = null
)
{
try
{
logger ??= Logger;
serializer ??= SnakeCaseSerializer;

using var requestMessage =
HttpClientExtensions.CreateHttpRequestMessageAndSetBaseFields(httpMethod, url, metricEntity, urlTemplate, headers, retryPolicySettings);

var content = request != null ? serializer.Serialize(request) : string.Empty;
requestMessage.Content = new StringContent(content, Encoding.UTF8, "application/json");

using var responseMessage = await httpClient.SendAsync(requestMessage);

return await responseMessage.GetStringFromHttpResponseAsync();
}
catch (Exception ex)
{
logger.ErrorWithObject(ex, new { httpMethod, url, request, headers });

return new OperationResult<string>(ex);
}
}

#endregion

#region Производные методы

[PublicAPI]
public static Task<OperationResult<TResponse>> GetAsync<TResponse>(
this HttpClient httpClient,
string url,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null
)
=> SendAsync<TResponse>(
httpClient,
HttpMethod.Get,
url,
metricEntity,
urlTemplate,
headers,
serializer,
retryPolicySettings
);

[PublicAPI]
public static Task<OperationResult<string>> PostAsync<TRequest>(
this HttpClient httpClient,
string url,
TRequest request,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null
)
=> SendAsync(
httpClient,
HttpMethod.Post,
url,
request,
metricEntity,
urlTemplate,
headers,
serializer,
retryPolicySettings
);

[PublicAPI]
public static Task<OperationResult<TResponse>> PostAsync<TRequest, TResponse>
(
this HttpClient httpClient,
string url,
TRequest request,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null
)
=> SendAsync<TRequest, TResponse>(
httpClient,
HttpMethod.Post,
url,
request,
metricEntity,
urlTemplate,
headers,
serializer,
retryPolicySettings
);

[PublicAPI]
public static Task<OperationResult<TResponse>> DeleteAsync<TRequest, TResponse>
(
this HttpClient httpClient,
string url,
TRequest request,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null
)
=> SendAsync<TRequest, TResponse>(
httpClient,
HttpMethod.Delete,
url,
request,
metricEntity,
urlTemplate,
headers,
serializer,
retryPolicySettings
);

[PublicAPI]
public static Task<OperationResult<string>> DeleteAsync
(
this HttpClient httpClient,
string url,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
RetryPolicySettings retryPolicySettings = null
)
=> httpClient.GetStringAsync(
HttpMethod.Delete,
url,
metricEntity,
urlTemplate,
headers,
retryPolicySettings
);

[PublicAPI]
public static Task<OperationResult<TResponse>> DeleteAsync<TResponse>
(
this HttpClient httpClient,
string url,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null
)
=> SendAsync<TResponse>(
httpClient,
HttpMethod.Delete,
url,
metricEntity,
urlTemplate,
headers,
serializer,
retryPolicySettings
);

[PublicAPI]
public static Task<OperationResult<string>> PutAsync<TRequest>(
this HttpClient httpClient,
string url,
TRequest request,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null
)
=> SendAsync(
httpClient,
HttpMethod.Put,
url,
request,
metricEntity,
urlTemplate,
headers,
serializer,
retryPolicySettings
);

[PublicAPI]
public static Task<OperationResult<TResponse>> PutAsync<TRequest, TResponse>
(
this HttpClient httpClient,
string url,
TRequest request,
string metricEntity,
string urlTemplate = null,
Dictionary<string, string> headers = null,
JsonSerializer serializer = null,
RetryPolicySettings retryPolicySettings = null
)
=> SendAsync<TRequest, TResponse>(
httpClient,
HttpMethod.Put,
url,
request,
metricEntity,
urlTemplate,
headers,
serializer,
retryPolicySettings
);

#endregion
}
Loading

0 comments on commit 8615548

Please sign in to comment.