From 4075420fb60a32d01a6d9a31379600843ab7f3bc Mon Sep 17 00:00:00 2001
From: bicijinlian <bicijinlian@noreply.gitcode.com>
Date: Tue, 13 Aug 2024 20:56:45 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF=E7=AE=A1=E7=90=86?=
 =?UTF-8?q?=E5=AE=8C=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Docs/1.3.0.基础使用.管理客户端.ipynb | 327 ++++++++++++++++++
 .../CustomHttpClient/CustomLogger.cs          |  23 ++
 .../CustomHttpClient/HelloApiService.cs       |  47 +++
 .../CustomHttpClient/Polly8ApiService.cs      |  60 ++++
 .../TokenDelegatingHandler.cs                 |  43 +++
 HttpClientStudy.Core/GlobalUsings.cs          |  38 +-
 6 files changed, 535 insertions(+), 3 deletions(-)
 create mode 100644 HttpClientStudy.Core/CustomHttpClient/CustomLogger.cs
 create mode 100644 HttpClientStudy.Core/CustomHttpClient/HelloApiService.cs
 create mode 100644 HttpClientStudy.Core/CustomHttpClient/Polly8ApiService.cs
 create mode 100644 HttpClientStudy.Core/CustomHttpClient/TokenDelegatingHandler.cs

diff --git a/Docs/1.3.0.基础使用.管理客户端.ipynb b/Docs/1.3.0.基础使用.管理客户端.ipynb
index 25e9830..d3bb494 100644
--- a/Docs/1.3.0.基础使用.管理客户端.ipynb
+++ b/Docs/1.3.0.基础使用.管理客户端.ipynb
@@ -48,6 +48,7 @@
    "source": [
     "//全局设置,行运行一次,为后续准备\n",
     "#r \"nuget:System.Net.Http.Json\"\n",
+    "#r \"nuget:Microsoft.Net.Http.Headers\"\n",
     "#r \"nuget:Microsoft.Extensions.Http\"\n",
     "#r \"nuget:Microsoft.Extensions.DependencyInjection\"\n",
     "#r \"nuget:Microsoft.Extensions.Logging\" \n",
@@ -1999,6 +2000,12 @@
    "cell_type": "code",
    "execution_count": null,
    "metadata": {
+    "dotnet_interactive": {
+     "language": "csharp"
+    },
+    "polyglot_notebook": {
+     "kernelName": "csharp"
+    },
     "vscode": {
      "languageId": "polyglot-notebook"
     }
@@ -2048,6 +2055,12 @@
    "cell_type": "code",
    "execution_count": null,
    "metadata": {
+    "dotnet_interactive": {
+     "language": "csharp"
+    },
+    "polyglot_notebook": {
+     "kernelName": "csharp"
+    },
     "vscode": {
      "languageId": "polyglot-notebook"
     }
@@ -2097,6 +2110,320 @@
    "source": [
     "## 8、综合管理:工厂 + 类型化客户端 + 请求管道 + Polly(默认使用 连接池和IoC容器)"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### 综合示例1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "dotnet_interactive": {
+     "language": "csharp"
+    },
+    "polyglot_notebook": {
+     "kernelName": "csharp"
+    },
+    "vscode": {
+     "languageId": "polyglot-notebook"
+    }
+   },
+   "outputs": [],
+   "source": [
+    "/* 综合示例1\n",
+    "   工厂 + 类型化客户端 + 管道 + Polly + 日志(自定义) \n",
+    "*/\n",
+    "\n",
+    "//类型化客户端\n",
+    "public class HelloApiService \n",
+    "{\n",
+    "    public HttpClient Client { get; set; }\n",
+    "\n",
+    "    public HelloApiService(HttpClient httpClient)\n",
+    "    {\n",
+    "        Client = httpClient;\n",
+    "    }\n",
+    "\n",
+    "    public async Task<string> Ping()\n",
+    "    {\n",
+    "        var content = await Client.GetStringAsync(\"/api/Hello/Ping\");\n",
+    "        return content;\n",
+    "    }\n",
+    "\n",
+    "    public async Task<string> Index()\n",
+    "    {\n",
+    "        var content = await Client.GetStringAsync(\"/api/Hello/Index\");\n",
+    "        return content;\n",
+    "    }\n",
+    "\n",
+    "    public async Task<string> Get()\n",
+    "    {\n",
+    "        var content = await Client.GetStringAsync(\"/api/Hello/Get\");\n",
+    "        return content;\n",
+    "    }\n",
+    "\n",
+    "    public async Task<string> Post()\n",
+    "    {\n",
+    "        var response = await Client.PostAsync(\"/api/Hello/Post\", null);\n",
+    "        var content = await response.Content.ReadAsStringAsync();\n",
+    "        return content;\n",
+    "    }\n",
+    "}\n",
+    "\n",
+    "//类开型客户端\n",
+    "public class Polly8ApiService \n",
+    "{\n",
+    "\n",
+    "    public HttpClient Client { get; set; }\n",
+    "\n",
+    "    public Polly8ApiService(HttpClient httpClient)\n",
+    "    {\n",
+    "        Client = httpClient;\n",
+    "    } \n",
+    "\n",
+    "    public async Task<string> Hello()\n",
+    "    {\n",
+    "        var content = await Client.GetStringAsync(\"/api/Polly8/Hello\");\n",
+    "        return content;\n",
+    "    }\n",
+    "\n",
+    "    public async Task<string> Exception()\n",
+    "    {\n",
+    "        var response = await Client.GetAsync(\"/api/Polly8/Exception\");\n",
+    "        response.EnsureSuccessStatusCode();\n",
+    "        var content = await response.Content.ReadAsStringAsync();\n",
+    "        return  content;\n",
+    "    }\n",
+    "\n",
+    "    public async Task<string> RetryException()\n",
+    "    {\n",
+    "        var response = await Client.GetAsync(\"/api/Polly8/RetryException\");\n",
+    "        response.EnsureSuccessStatusCode();\n",
+    "        var content = await response.Content.ReadAsStringAsync();\n",
+    "        return  content;\n",
+    "    }\n",
+    "\n",
+    "    public async Task<string> RandomException()\n",
+    "    {\n",
+    "        var response = await Client.GetAsync(\"/api/Polly8/RandomException\");\n",
+    "        response.EnsureSuccessStatusCode();\n",
+    "        var content = await response.Content.ReadAsStringAsync();\n",
+    "        return  content;\n",
+    "    }\n",
+    "\n",
+    "    public async Task<string> ToggleException()\n",
+    "    {\n",
+    "        var response = await Client.GetAsync(\"/api/Polly8/ToggleException?toggleId=\"+Guid.NewGuid().ToString());\n",
+    "        response.EnsureSuccessStatusCode();\n",
+    "        var content = await response.Content.ReadAsStringAsync();\n",
+    "        return  content;\n",
+    "    }\n",
+    "}\n",
+    "\n",
+    "//Token管理中间件\n",
+    "public class TokenDelegatingHandler : DelegatingHandler \n",
+    "{\n",
+    "    protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)\n",
+    "    {\n",
+    "        Console.WriteLine(\"TokenDelegatingHandler -> Send -> Added Token\");\n",
+    "\n",
+    "        if (!request.Headers.Contains(Microsoft.Net.Http.Headers.HeaderNames.Authorization)) \n",
+    "        {\n",
+    "            Console.WriteLine(\"没有 Token, TokenDelegatingHandler 添加之\");\n",
+    "            request.Headers.Add(Microsoft.Net.Http.Headers.HeaderNames.Authorization, \"Bearer \" + \"a.b.c\");\n",
+    "        }\n",
+    "        else\n",
+    "        {\n",
+    "            Console.WriteLine($\"已有Token, {request.Headers.Authorization}\");\n",
+    "        }\n",
+    "\n",
+    "        HttpResponseMessage response = base.Send(request, cancellationToken);\n",
+    "\n",
+    "        Console.WriteLine(\"TokenDelegatingHandler -> Send -> After\");\n",
+    "\n",
+    "        return response;\n",
+    "    }\n",
+    "\n",
+    "    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\n",
+    "    {\n",
+    "        Console.WriteLine(\"TokenDelegatingHandler -> SendAsync -> Before\");\n",
+    "\n",
+    "        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);\n",
+    "\n",
+    "        Console.WriteLine(\"TokenDelegatingHandler -> SendAsync -> After\");\n",
+    "\n",
+    "        return response;\n",
+    "    }\n",
+    "}\n",
+    "\n",
+    "//自定义日志\n",
+    "public class CustomLogger : IHttpClientLogger\n",
+    "{\n",
+    "    public object? LogRequestStart(HttpRequestMessage request)\n",
+    "    {\n",
+    "        return null;\n",
+    "    }\n",
+    "\n",
+    "    public void LogRequestStop(object? ctx, HttpRequestMessage request, HttpResponseMessage response, TimeSpan elapsed)\n",
+    "    {\n",
+    "        Console.WriteLine($\"自定义日志:{request.Method} {request.RequestUri?.AbsoluteUri} - {(int)response.StatusCode} {response.StatusCode} in {elapsed.TotalMilliseconds}ms\");\n",
+    "    }\n",
+    "\n",
+    "    public void LogRequestFailed(object? ctx, HttpRequestMessage request, HttpResponseMessage? response, Exception e, TimeSpan elapsed)\n",
+    "    {\n",
+    "        Console.WriteLine($\"自定义日志:{request.Method} {request.RequestUri?.AbsoluteUri} - Exception {e.GetType().FullName}: {e.Message}\");\n",
+    "    }\n",
+    "}\n",
+    "\n",
+    "//polly策略\n",
+    "var policy = Policy\n",
+    "    .Handle<HttpRequestException>()\n",
+    "    .OrResult<HttpResponseMessage>(message => message.StatusCode != System.Net.HttpStatusCode.OK)\n",
+    "    .WaitAndRetryAsync(new TimeSpan[]{TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2),TimeSpan.FromSeconds(4),});\n",
+    "\n",
+    "//使用\n",
+    "{\n",
+    "    var services = new ServiceCollection();\n",
+    "\n",
+    "    //注册基础类型\n",
+    "    services\n",
+    "        //注册日志类\n",
+    "        .AddTransient<CustomLogger>()\n",
+    "        .AddScoped<TokenDelegatingHandler>()\n",
+    "        ;\n",
+    "\n",
+    "    //基础配置\n",
+    "    services\n",
+    "        // 基础日志配置(默认日志)\n",
+    "        .AddLogging(builder => \n",
+    "        {\n",
+    "            //日志级别\n",
+    "            builder.SetMinimumLevel(LogLevel.Trace);\n",
+    "\n",
+    "            //控制台日志\n",
+    "            builder.AddConsole();\n",
+    "        })\n",
+    "        //全局配置\n",
+    "        .ConfigureHttpClientDefaults(clientBuilder =>\n",
+    "        {\n",
+    "            clientBuilder.AddDefaultLogger();\n",
+    "            clientBuilder.ConfigureHttpClient(client => \n",
+    "            {\n",
+    "                client.BaseAddress = new Uri(webApiBaseUrl);\n",
+    "            });\n",
+    "        });\n",
+    "\n",
+    "        //默认命名客户端\n",
+    "        services.AddHttpClient<HttpClient>(string.Empty, config => \n",
+    "        {\n",
+    "            config.DefaultRequestHeaders.Add(\"X-Custom-Demo\", \"true\");\n",
+    "        })\n",
+    "        //配置客户端\n",
+    "        .ConfigureHttpClient(client => \n",
+    "        {\n",
+    "            //client.BaseAddress = new Uri(webApiBaseUrl);\n",
+    "            client.Timeout = TimeSpan.FromSeconds(10);\n",
+    "        })\n",
+    "        //添加类型化客户端\n",
+    "        .AddTypedClient<HelloApiService>()\n",
+    "        //添加自定义管道\n",
+    "        .AddHttpMessageHandler<TokenDelegatingHandler>()\n",
+    "        //添加默认日志:全局配置已添加\n",
+    "        //.AddDefaultLogger()\n",
+    "        //添加自定义日志\n",
+    "        .AddLogger<CustomLogger>()\n",
+    "        //日志转发头(所有请求头)\n",
+    "        .RedactLoggedHeaders( headerName => true)\n",
+    "\n",
+    "        //配置SocketsHttpHandler\n",
+    "        .UseSocketsHttpHandler(config =>\n",
+    "        {\n",
+    "            //配置连接池等\n",
+    "            config.Configure((handler,provider) => \n",
+    "            {\n",
+    "                handler.AllowAutoRedirect = true;\n",
+    "                handler.PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30);\n",
+    "                handler.PooledConnectionLifetime = TimeSpan.FromSeconds(30);\n",
+    "                handler.UseProxy = false;\n",
+    "                handler.UseCookies = true;\n",
+    "            });\n",
+    "        })\n",
+    "        //设置生命周期\n",
+    "        .SetHandlerLifetime(TimeSpan.FromSeconds(30))\n",
+    "        //Polly策略配置\n",
+    "        .AddPolicyHandler(policy)\n",
+    "        //便捷配置\n",
+    "        .AddTransientHttpErrorPolicy(builder => builder.CircuitBreakerAsync<HttpResponseMessage>(11, TimeSpan.FromSeconds(30)))\n",
+    "        ;\n",
+    "\n",
+    "    //自定义\n",
+    "    services.AddHttpClient<HttpClient>(\"ClientA\", config => \n",
+    "        {\n",
+    "            config.DefaultRequestHeaders.Add(\"X-Custom-Demo\", \"ClientA\");\n",
+    "        })\n",
+    "        //配置客户端\n",
+    "        .ConfigureHttpClient(client => \n",
+    "        {\n",
+    "            //client.BaseAddress = new Uri(webApiBaseUrl);\n",
+    "            client.Timeout = TimeSpan.FromSeconds(10);\n",
+    "        })\n",
+    "        //添加类型化客户端\n",
+    "        .AddTypedClient<Polly8ApiService>()\n",
+    "        //添加自定义管道\n",
+    "        .AddHttpMessageHandler<TokenDelegatingHandler>()\n",
+    "        //添加默认日志:全局配置已添加\n",
+    "        //.AddDefaultLogger()\n",
+    "        //添加自定义日志\n",
+    "        .AddLogger<CustomLogger>()\n",
+    "        //日志转发头(所有请求头)\n",
+    "        .RedactLoggedHeaders( headerName => true)\n",
+    "        //配置SocketsHttpHandler\n",
+    "        .UseSocketsHttpHandler(config =>\n",
+    "        {\n",
+    "            //配置连接池等\n",
+    "            config.Configure((handler,provider) => \n",
+    "            {\n",
+    "                handler.AllowAutoRedirect = true;\n",
+    "                handler.PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30);\n",
+    "                handler.PooledConnectionLifetime = TimeSpan.FromSeconds(30);\n",
+    "                handler.UseProxy = false;\n",
+    "                handler.UseCookies = true;\n",
+    "            });\n",
+    "        })\n",
+    "        //设置生命周期\n",
+    "        .SetHandlerLifetime(TimeSpan.FromSeconds(30))\n",
+    "        //Polly策略配置\n",
+    "        .AddPolicyHandler(policy)\n",
+    "        //便捷配置\n",
+    "        .AddTransientHttpErrorPolicy(builder => builder.CircuitBreakerAsync<HttpResponseMessage>(11, TimeSpan.FromSeconds(30)))\n",
+    "        ;\n",
+    "\n",
+    "    var factory = services.BuildServiceProvider().GetRequiredService<IHttpClientFactory>();\n",
+    "\n",
+    "    var defaultClient = factory.CreateClient();\n",
+    "    var defaultContent = await defaultClient.GetStringAsync(\"api/hello/ping\");\n",
+    "    Console.WriteLine(defaultContent);\n",
+    "\n",
+    "    var clientA = factory.CreateClient();\n",
+    "    var contentA = await clientA.GetStringAsync(\"api/polly8/hello\");\n",
+    "    Console.WriteLine(contentA);\n",
+    "\n",
+    "    //类型化客户端\n",
+    "    HelloApiService helloApiService = services.BuildServiceProvider().GetRequiredService<HelloApiService>();\n",
+    "    Console.WriteLine(await helloApiService.Ping());\n",
+    "    Console.WriteLine(await helloApiService.Index());\n",
+    "    Console.WriteLine(await helloApiService.Get());\n",
+    "    Console.WriteLine(await helloApiService.Post());\n",
+    "\n",
+    "    Polly8ApiService polly8ApiService = services.BuildServiceProvider().GetRequiredService<Polly8ApiService>();\n",
+    "    Console.WriteLine(await polly8ApiService.Hello());\n",
+    "\n",
+    "}\n"
+   ]
   }
  ],
  "metadata": {
diff --git a/HttpClientStudy.Core/CustomHttpClient/CustomLogger.cs b/HttpClientStudy.Core/CustomHttpClient/CustomLogger.cs
new file mode 100644
index 0000000..08cf7be
--- /dev/null
+++ b/HttpClientStudy.Core/CustomHttpClient/CustomLogger.cs
@@ -0,0 +1,23 @@
+namespace HttpClientStudy.Core.CustomHttpClient
+{
+    /// <summary>
+    /// 自定义日志
+    /// </summary>
+    public class CustomLogger : IHttpClientLogger
+    {
+        public object? LogRequestStart(HttpRequestMessage request)
+        {
+            return null;
+        }
+
+        public void LogRequestStop(object? ctx, HttpRequestMessage request, HttpResponseMessage response, TimeSpan elapsed)
+        {
+            Console.WriteLine($"自定义日志:{request.Method} {request.RequestUri?.AbsoluteUri} - {(int)response.StatusCode} {response.StatusCode} in {elapsed.TotalMilliseconds}ms");
+        }
+
+        public void LogRequestFailed(object? ctx, HttpRequestMessage request, HttpResponseMessage? response, Exception e, TimeSpan elapsed)
+        {
+            Console.WriteLine($"自定义日志:{request.Method} {request.RequestUri?.AbsoluteUri} - Exception {e.GetType().FullName}: {e.Message}");
+        }
+    }
+}
diff --git a/HttpClientStudy.Core/CustomHttpClient/HelloApiService.cs b/HttpClientStudy.Core/CustomHttpClient/HelloApiService.cs
new file mode 100644
index 0000000..93aa6a8
--- /dev/null
+++ b/HttpClientStudy.Core/CustomHttpClient/HelloApiService.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HttpClientStudy.Core.CustomHttpClient
+{
+    /// <summary>
+    /// HelloApi
+    /// 类型化客户端
+    /// </summary>
+    public class HelloApiService
+    {
+        public HttpClient Client { get; set; }
+
+        public HelloApiService(HttpClient httpClient)
+        {
+            Client = httpClient;
+        }
+
+        public async Task<string> Ping()
+        {
+            var content = await Client.GetStringAsync("/api/Hello/Ping");
+            return content;
+        }
+
+        public async Task<string> Index()
+        {
+            var content = await Client.GetStringAsync("/api/Hello/Index");
+            return content;
+        }
+
+        public async Task<string> Get()
+        {
+            var content = await Client.GetStringAsync("/api/Hello/Get");
+            return content;
+        }
+
+        public async Task<string> Post()
+        {
+            var response = await Client.PostAsync("/api/Hello/Post", null);
+            var content = await response.Content.ReadAsStringAsync();
+            return content;
+        }
+    }
+}
diff --git a/HttpClientStudy.Core/CustomHttpClient/Polly8ApiService.cs b/HttpClientStudy.Core/CustomHttpClient/Polly8ApiService.cs
new file mode 100644
index 0000000..a87a11d
--- /dev/null
+++ b/HttpClientStudy.Core/CustomHttpClient/Polly8ApiService.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HttpClientStudy.Core.CustomHttpClient
+{
+    /// <summary>
+    /// Polly V8
+    /// 类型化客户端
+    /// </summary>
+    public class Polly8ApiService
+    {
+        public HttpClient Client { get; set; }
+
+        public Polly8ApiService(HttpClient httpClient)
+        {
+            Client = httpClient;
+        }
+
+        public async Task<string> Hello()
+        {
+            var content = await Client.GetStringAsync("/api/Polly8/Hello");
+            return content;
+        }
+
+        public async Task<string> Exception()
+        {
+            var response = await Client.GetAsync("/api/Polly8/Exception");
+            response.EnsureSuccessStatusCode();
+            var content = await response.Content.ReadAsStringAsync();
+            return content;
+        }
+
+        public async Task<string> RetryException()
+        {
+            var response = await Client.GetAsync("/api/Polly8/RetryException");
+            response.EnsureSuccessStatusCode();
+            var content = await response.Content.ReadAsStringAsync();
+            return content;
+        }
+
+        public async Task<string> RandomException()
+        {
+            var response = await Client.GetAsync("/api/Polly8/RandomException");
+            response.EnsureSuccessStatusCode();
+            var content = await response.Content.ReadAsStringAsync();
+            return content;
+        }
+
+        public async Task<string> ToggleException()
+        {
+            var response = await Client.GetAsync("/api/Polly8/ToggleException?toggleId=" + Guid.NewGuid().ToString());
+            response.EnsureSuccessStatusCode();
+            var content = await response.Content.ReadAsStringAsync();
+            return content;
+        }
+    }
+}
diff --git a/HttpClientStudy.Core/CustomHttpClient/TokenDelegatingHandler.cs b/HttpClientStudy.Core/CustomHttpClient/TokenDelegatingHandler.cs
new file mode 100644
index 0000000..d38242e
--- /dev/null
+++ b/HttpClientStudy.Core/CustomHttpClient/TokenDelegatingHandler.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Microsoft.Net.Http.Headers;
+
+namespace HttpClientStudy.Core.CustomHttpClient
+{
+    /// <summary>
+    /// oken管理中间件
+    /// </summary>
+    public class TokenDelegatingHandler : DelegatingHandler 
+    {
+        protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
+        {
+            Console.WriteLine("TokenDelegatingHandler -> Send -> Added Token");
+
+            if (request.Headers.Authorization is null) 
+            {
+                request.Headers.Add(HeaderNames.Accept, "Bearer " + "a.b.c");
+            }
+
+            HttpResponseMessage response = base.Send(request, cancellationToken);
+
+            Console.WriteLine("TokenDelegatingHandler -> Send -> After");
+
+            return response;
+        }
+
+        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+        {
+            Console.WriteLine("TokenDelegatingHandler -> SendAsync -> Before");
+
+            HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
+
+            Console.WriteLine("TokenDelegatingHandler -> SendAsync -> After");
+
+            return response;
+        }
+    }
+}
diff --git a/HttpClientStudy.Core/GlobalUsings.cs b/HttpClientStudy.Core/GlobalUsings.cs
index 25ab24c..04f9c70 100644
--- a/HttpClientStudy.Core/GlobalUsings.cs
+++ b/HttpClientStudy.Core/GlobalUsings.cs
@@ -3,14 +3,46 @@ global using System.Linq;
 global using System.Text;
 global using System.Threading;
 global using System.Threading.Tasks;
-global using System.Collections.Generic;
-
-global using System.Net;
 global using System.Net.Mime;
 global using System.Net.Http;
 global using System.Net.Http.Json;
 global using System.Net.Http.Headers;
 
+global using Microsoft.Extensions.Configuration;
+global using Microsoft.Extensions.Configuration.Memory;
+global using Microsoft.Extensions.Configuration.CommandLine;
+global using Microsoft.Extensions.Configuration.EnvironmentVariables;
+global using Microsoft.Extensions.Configuration.UserSecrets;
+global using Microsoft.Extensions.Configuration.KeyPerFile;
+global using Microsoft.Extensions.Configuration.Ini;
+global using Microsoft.Extensions.Configuration.Json;
+global using Microsoft.Extensions.Configuration.Xml;
+global using Microsoft.Extensions.Options;
+global using Microsoft.Extensions.DependencyInjection;
+global using Microsoft.Extensions.DependencyInjection.Extensions;
+
+global using Microsoft.Net.Http;
+global using Microsoft.Net.Http.Headers;
+global using Microsoft.Extensions.Http;
+global using Microsoft.Extensions.Http.Logging;
+
+global using Polly;
+global using Polly.NoOp;
+global using Polly.Retry;
+global using Polly.Bulkhead;
+global using Polly.Fallback;
+global using Polly.Hedging;
+global using Polly.RateLimit;
+global using Polly.Caching;
+global using Polly.Timeout;
+global using Polly.CircuitBreaker;
+global using Polly.Wrap;
+global using Polly.Registry;
+global using Polly.Utilities;
+global using Polly.Telemetry;
+global using Polly.Extensions;
+global using Polly.Extensions.Http;
+
 global using HttpClientStudy.Config;
 global using HttpClientStudy.Model;