ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 要求_玖富


玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。

能够注册 IHttpClientFactory 并将其用于设置装备摆设和建立运用中的 HttpClient 实例。 这能带来以下优点:

  • 供应一个中心地位,用于定名和设置装备摆设逻辑 HttpClient 实例。 比方,能够注册 github 客户端,并将它设置装备摆设为接见 GitHub。 能够注册一个默许客户端用于其他用处。
  • 经由过程托付 HttpClient 中的处置惩罚顺序整顿出站中间件的观点,并供应适用于基于 Polly 的中间件的扩大来应用观点。
  • 治理基础 HttpClientMessageHandler 实例的池和生存期,制止在手动治理 HttpClient 生存期时涌现罕见的 DNS 题目。
  • (经由过程 ILogger)增加可设置装备摆设的纪录体验,以处置惩罚工场建立的客户端发送的一切要求。

在运用中能够经由过程以下多种体式格局运用 IHttpClientFactory

基础用法

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddHttpClient();
        }

 

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private readonly IHttpClientFactory _clientFactory;
        public ValuesController(IHttpClientFactory clientFactory)
        {
            _clientFactory = clientFactory;
        }

        // GET api/values
        [HttpGet]
        public async Task<string> Get()
        {
            HttpClient client = _clientFactory.CreateClient();

            //要领一:
            //HttpRequestMessage request = new HttpRequestMessage
            //{
            //    Method = new HttpMethod("get"),
            //    RequestUri = new System.Uri("http://localhost:5000/api/values"),
            //};
            //HttpResponseMessage response = await client.SendAsync(request);
            //string res = await response.Content.ReadAsStringAsync();
            //return res;

            //要领二:
            string res = await client.GetStringAsync("http://localhost:5000/api/values");
            return res;
        }
     }

 

定名客户端

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
 services.AddHttpClient("test", c =>
            {
                c.BaseAddress = new Uri("http://localhost:5000"); });
        }

 

        public async Task<string> Get()
        {
            HttpClient client = _clientFactory.CreateClient("test");
            //注册名叫 "test" 的客户端时,已指定了该客户端的要求基地点,以是这里不须要指定主机名了
            return await client.GetStringAsync("api/values");
        }

 

范例化客户端

    public class TestHttpClient
    {
        public HttpClient Client { get; set; }

        public TestHttpClient(HttpClient client)
        {
            client.BaseAddress = new System.Uri("http://localhost:5000");
            Client = client;
        }

        public async Task<string> Get()
        {
            return await Client.GetStringAsync("api/values");
        }
    }

 

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddHttpClient<TestHttpClient>(c =>
            {
                //能够在这里设置,也能够在组织函数设置.
                //c.BaseAddress = new System.Uri("http://localhost:5000");
            });
        }

 

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private readonly TestHttpClient _client;

        public ValuesController(TestHttpClient client)
        {
            _client = client;
        }
     
        [HttpGet]
        public async Task<string> Get()
        {
            return await _client.Get();
        }
    }

 

出站要求中间件

HttpClient 已具有托付处置惩罚顺序的观点,这些托付处置惩罚顺序能够链接在一起,处置惩罚出站 HTTP 要求。 IHttpClientFactory 能够轻松界说处置惩罚顺序并运用于每一个定名客户端。 它支撑注册和链接多个处置惩罚顺序,以天生出站要求中间件管道。 每一个处置惩罚顺序都能够在出站要求前后实行工作。 此形式类似于 ASP.NET Core 中的入站中间件管道。 它供应了一种用于治理缭绕 HTTP 要求的横切关注点的机制,包孕缓存、错误处置惩罚、序列化和日记纪录。

要建立处置惩罚顺序,须要界说一个派生自 DelegatingHandler 的类。 重写 SendAsync 要领,在将要求通报至管道中的下一个处置惩罚顺序之前实行代码:

    public class ValidateHeaderHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (!request.Headers.Contains("refuge"))
            {
                return new HttpResponseMessage(HttpStatusCode.BadRequest)
                {
                    Content = new StringContent("not found refuge")
                };
            }

            return await base.SendAsync(request, cancellationToken);
        }
    }

 

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
 services.AddTransient<ValidateHeaderHandler>();//生存期必需是暂时
            services.AddHttpClient("test", c =>
                {
                    c.BaseAddress = new Uri("http://localhost:5000");
                })
                .AddHttpMessageHandler<ValidateHeaderHandler>();
        }

 

HttpClient 和生存期治理

每次对 IHttpClientFactory 挪用 CreateClient 都邑返回一个新 HttpClient 实例:

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。-
        public IEnumerable<int> Get()
        {
            //测试生存期
            for (int i = 0; i < 4; i  )
            {
                HttpClient client = i % 2 == 0
                    ? _clientFactory.CreateClient("test")
                    : _clientFactory.CreateClient();
                yield return client.GetHashCode();
            }
        }

 

 

CreateClient 要领内部会挪用 CreateHandler 要领,后者建立 HttpMessageHandler,

源码以下:

    public HttpClient CreateClient(string name)
    {
      if (name == null)
        throw new ArgumentNullException(nameof (name));
      HttpClient httpClient = new HttpClient(this.CreateHandler(name), false);
      HttpClientFactoryOptions clientFactoryOptions = this._optionsMonitor.Get(name);
      for (int index = 0; index < clientFactoryOptions.HttpClientActions.Count;   index)
        clientFactoryOptions.HttpClientActions[index](httpClient);
      return httpClient;
    }

 

    public HttpMessageHandler CreateHandler(string name)
    {
      if (name == null)
        throw new ArgumentNullException(nameof (name));
      ActiveHandlerTrackingEntry entry = this._activeHandlers.GetOrAdd(name, this._entryFactory).Value;
      this.StartHandlerEntryTimer(entry);
      return (HttpMessageHandler) entry.Handler;
    }

 

而这个 _activeHandlers 的范例是 : 

一个线程平安的键值对鸠合.

因而,实际上建立的 HttpMessageHandler 实例会搜集到池中.新建 HttpClient 实例时,可能会重用池中的 HttpMessageHandler 实例(若是生存期还没有到期的话). 

因为每一个处置惩罚顺序一般治理本身的基础 HTTP 衔接,因而须要池化处置惩罚顺序.建立超越须要数目的处置惩罚顺序可能会致使衔接耽误. 局部处置惩罚顺序还连结衔接无限期地翻开,如许能够防备处置惩罚顺序对 DNS 变动作出反应.

处置惩罚顺序的默许生存期为两分钟,可在每一个定名客户端上重写默许值:

services.AddHttpClient("test").SetHandlerLifetime(TimeSpan.FromMinutes(5));

 

设置装备摆设 HttpMessageHandler

有时候,我们须要掌握客户端运用的内部 HttpMessageHandler .

            services.AddHttpClient("test")
                .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
                {
                    AllowAutoRedirect = false,
                });

 

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。