-
Notifications
You must be signed in to change notification settings - Fork 0
/
ServiceCollectionExtension.cs
118 lines (106 loc) · 5.79 KB
/
ServiceCollectionExtension.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
namespace Salt.HttpClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Extensions.Http;
/// <summary>
/// Inject SaltHttpClients to IServiceCollection
/// </summary>
public static class ServiceCollectionExtension
{
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(int times) =>
HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode is HttpStatusCode.NotFound)
.WaitAndRetryAsync(times, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
/// <summary>
/// Добавление в DI типизированного httpClient
/// </summary>
/// <param name="serviceCollection">IServiceCollection</param>
/// <param name="baseUrl">базовый Url конечного узла</param>
/// <param name="timeout">Таймаут запроса</param>
/// <param name="handlerLifetime">HttpHandler lifetime. If null, set as Timespan.FromMinutes(5)</param>
/// <param name="baseHeaders">Базовые headers для каждого запроса</param>
/// <param name="retryNumber">Количество попыток подключения, если в качестве ответов падают ошибки 5ХХ, 408 (timeout) или 404 (notFound)</param>
/// <typeparam name="TRealization">Тип, наследующися от AbstractHttpClient</typeparam>
/// <returns></returns>
public static IServiceCollection AddSaltHttpClient<TRealization>(this IServiceCollection serviceCollection
, Uri baseUrl
, TimeSpan? timeout = null
, TimeSpan? handlerLifetime = null
, HttpHeaders baseHeaders = null
, int retryNumber = 0)
where TRealization : AbstractHttpClient
{
IHttpClientBuilder httpClientBuilder = serviceCollection.AddHttpClient<TRealization>(httpClient =>
HttpClientConfig(httpClient, baseUrl, timeout, baseHeaders));
HttpClientBuilderConfig(httpClientBuilder, handlerLifetime, retryNumber);
return serviceCollection;
}
/// <summary>
/// Добавление в DI типизированного httpClient
/// </summary>
/// <param name="serviceCollection">IServiceCollection</param>
/// <param name="baseUrl">базовый Url конечного узла</param>
/// <param name="timeout">Таймаут запроса</param>
/// <param name="handlerLifetime">HttpHandler lifetime. If null, set as Timespan.FromMinutes(5)</param>
/// <param name="baseHeaders">Базовые headers для каждого запроса</param>
/// <param name="retryNumber">Количество попыток подключения, если в качестве ответов падают ошибки 5ХХ, 408 (timeout) или 404 (notFound)</param>
/// <typeparam name="TClient">Тип типа клиента. Будет зарегистрирован как Transient</typeparam>
/// <typeparam name="TRealization">Тип, наследующися от AbstractHttpClient</typeparam>
/// <returns></returns>
public static IServiceCollection AddSaltHttpClient<TClient, TRealization>(this IServiceCollection serviceCollection
, Uri baseUrl
, TimeSpan? timeout = null
, TimeSpan? handlerLifetime = null
, HttpHeaders baseHeaders = null
, int retryNumber = 0)
where TClient : class
where TRealization : AbstractHttpClient, TClient
{
IHttpClientBuilder httpClientBuilder = serviceCollection.AddHttpClient<TClient, TRealization>(httpClient =>
HttpClientConfig(httpClient, baseUrl, timeout, baseHeaders));
HttpClientBuilderConfig(httpClientBuilder, handlerLifetime, retryNumber);
return serviceCollection;
}
#region private
/// <summary>
/// Настроить HttpClient
/// </summary>
/// <param name="httpClient">Созданный httpClient</param>
/// <param name="baseUrl">базовый Url конечного узла</param>
/// <param name="timeout">Таймаут запроса</param>
/// <param name="baseHeaders">Базовые headers для каждого запроса</param>
private static void HttpClientConfig(System.Net.Http.HttpClient httpClient
, Uri baseUrl
, TimeSpan? timeout = null
, HttpHeaders baseHeaders = null)
{
httpClient.BaseAddress = baseUrl;
if (timeout.HasValue)
httpClient.Timeout = timeout.Value;
if (baseHeaders != null && baseHeaders.Any())
foreach (KeyValuePair<string, IEnumerable<string>> header in baseHeaders)
httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
}
/// <summary>
/// Настроить IHttpClientBuilder
/// </summary>
/// <param name="httpClientBuilder">Созданный IHttpClientBuilder</param>
/// <param name="handlerLifetime">HttpHandler lifetime. If null, set as Timespan.FromMinutes(5)</param>
/// <param name="retryNumber">Количество попыток подключения, если в качестве ответов падают ошибки 5ХХ, 408 (timeout) или 404 (notFound)</param>
private static void HttpClientBuilderConfig(IHttpClientBuilder httpClientBuilder
, TimeSpan? handlerLifetime = null
, int retryNumber = 0)
{
httpClientBuilder.SetHandlerLifetime(handlerLifetime ?? TimeSpan.FromMinutes(5));
if (retryNumber > 0)
httpClientBuilder.AddPolicyHandler(GetRetryPolicy(retryNumber));
}
#endregion
}