首页 > 其他分享 >dotnet平台Http消息处理者工厂

dotnet平台Http消息处理者工厂

时间:2023-05-22 09:25:00浏览次数:45  
标签:Http HttpMessageHandlerFactory 工厂 Extensions dotnet return Microsoft 客户端

1 前言

Microsoft.Extensions.Http是一个设计非常优异的客户端工厂库,其提供了IHttpClientFactory用于创建HttpClientIHttpMessageHandlerFactory用于创建HttpMessageHandler

遗憾的是这个库目前仅非常试用于客户端,而不太适用于转发端。我们对客户端的定义是一个软件在某种业务下使用单账号请求远程服务器的客户端行为,此软件不再充当其它软件的服务端;对转发端的定义是一个软件运行时,帮它的的多个客户端请求远程服务器,同时一般对远程服务器的响应内容做一些包装或修改的软件。

有时哪怕是做客户端软件,当遇到下面需求时,HttpClient和Microsoft.Extensions.Http的者难以解决:

  1. 可以临时申请很多代理服务器
  2. 每个代理服务器能使用3分钟
  3. 使用这些代理服务器源源不断的请求到某站

如果我们使用Microsoft.Extensions.Http,则无法使用动态的代理服务器;如果我们使用动态创建和维护多个HttpClient实例,我们又回到造第二个Microsoft.Extensions.Http的需求。

2 HttpMessageHandlerFactory

HttpMessageHandlerFactory就是上面要造第二Microsoft.Extensions.Http的需求的产物,其它核心接口定义如下:

/// <summary>
/// Http消息处理者工厂
/// </summary>
public interface IHttpMessageHandlerFactory
{
    /// <summary>
    /// 创建用于请求的HttpMessageHandler
    /// </summary>
    /// <param name="name">别名</param>
    /// <param name="proxyUri">支持携带UserInfo的代理地址</param> 
    /// <returns></returns>
    HttpMessageHandler CreateHandler(string name, Uri? proxyUri);
}

当然HttpMessageHandlerFactory也提供了和Microsoft.Extensions.Http相似的Builder能力,在使用服务注册时没有额外的学习成本。

2.1 可选的ProxyUri参数

接口多了一个可选的Uri参数,有值的时候,代表要使用这个参数做代理。别小看这个Uri参数,它是可继承的类型,传入Uri的子类型还可以实现很多意想不到的骚操作。

2.2 支持创建HttpClient

IHttpMessageHandlerFactory提供创建HttpClient的扩展,用于做客户端模式,且支持传入与用户实例绑定的CookieContainer,然后Cookie就完全自动化处理。

/// <summary>
/// 创建Http客户端
/// </summary>
/// <param name="factory"></param>
/// <param name="name">别名</param>
/// <param name="proxyUri">支持携带UserInfo的代理地址</param>
/// <param name="cookieContainer">cookie容器</param>
/// <returns></returns>
public static HttpClient CreateClient(this IHttpMessageHandlerFactory factory, string name, Uri? proxyUri = null, CookieContainer? cookieContainer = null)
{
    var httpHandler = factory.CreateHandler(name, proxyUri, cookieContainer);
    return new HttpClient(httpHandler, disposeHandler: false);
}

2.3 支持创建HttpMessageInvoker

IHttpMessageHandlerFactory提供创建HttpMessageInvoker的扩展,用于转发端模式,且支持传入与用户实例绑定的CookieContainer,然后Cookie就完全自动化处理。

/// <summary>
/// 创建Http执行器
/// </summary>
/// <param name="factory"></param>
/// <param name="name">别名</param>
/// <param name="proxyUri">支持携带UserInfo的代理地址</param>
/// <param name="cookieContainer">cookie容器</param>
/// <returns></returns>
public static HttpMessageInvoker CreateInvoker(this IHttpMessageHandlerFactory factory, string name, Uri? proxyUri = null, CookieContainer? cookieContainer = null)
{
    var httpHandler = factory.CreateHandler(name, proxyUri, cookieContainer);
    return new HttpMessageInvoker(httpHandler, disposeHandler: false);
}

3 生态与扩展

如果说HttpMessageHandlerFactory只解决了Microsoft.Extensions.Http的Proxy痛点,但丢了Microsoft.Extensions.Http的生态又不能扩展的话,那无疑HttpMessageHandlerFactory是非常局限和失败的。

实际上Microsoft.Extensions.Http上层的很多组件,移植到HttpMessageHandlerFactory是非常简单的,简单说是DI注册扩展的IHttpClientBuilder改为IHttpMessageHandlerBuilder就行。

3.1 HttpMessageHandlerFactory.Polly

为HttpMessageHandlerFactory提供Polly策略扩展,使得IHttpMessageHandlerBuilder拥有与IHttpClientFactory完全一致的Polly能力。

3.1.1 AddPolicyHandler能力

var retryPolicy = Policy.Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(response =>
    {
        return response.IsSuccessStatusCode == false;
    }).WaitAndRetryAsync(3, t => TimeSpan.FromSeconds(3d));

 services
    .AddHttpMessageHandlerFactory("App")
    .AddPolicyHandler(retryPolicy);    

3.1.2 AddPolicyHandlerFromRegistry能力

var retryPolicy = Policy.Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(response =>
    {
        return response.IsSuccessStatusCode == false;
    }).WaitAndRetryAsync(3, t => TimeSpan.FromSeconds(3d));

var registry = services.AddPolicyRegistry();
registry.Add("registry1", retryPolicy);

services
    .AddHttpMessageHandlerFactory("App")
    .AddPolicyHandlerFromRegistry("registry1");    

3.1.3 AddTransientHttpErrorPolicy能力

当以下任意条件成立时,触发TransientHttpErrorPolicy

  • HttpRequestException的网络故障
  • 服务端响应5XX的状态码
  • 408的状态码(request timeout)
services
    .AddHttpMessageHandlerFactory("App")
    .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[] {
        TimeSpan.FromSeconds(1d),
        TimeSpan.FromSeconds(5d),
        TimeSpan.FromSeconds(10d)
    }));  

3.2 HttpMessageHandlerFactory.Connection

为HttpMessageHandlerFactory提供自定义连接的功能。
注意此扩展项目不是免费项目,有如下限制:

  • 不开放和提供源代码
  • nuget包的程序集在应用程序运行2分钟后适用期结束
  • 适用期结束后所有的http请求响应为423 Locked
  • 需要license文件授权方可完全使用

3.2.1 自定义域名解析

  • 当无代理连接时,连接到自定义解析得到的IP
  • 当使用http代理时,让代理服务器连接到自定义解析得到的IP
  • 当使用socks代理时,让代理服务器连接到自定义解析得到的IP
services
    .AddHttpMessageHandlerFactory("App")
    .AddHostResolver<CustomHostResolver>();
sealed class CustomHostResolver : HostResolver
{
    public override ValueTask<HostPort> ResolveAsync(DnsEndPoint endpoint, CancellationToken cancellationToken)
    {
        if (endpoint.Host == "www.baidu.com")
        {
            return ValueTask.FromResult(new HostPort("14.119.104.189", endpoint.Port));
        }
        return ValueTask.FromResult(new HostPort(endpoint.Host, endpoint.Port));
    }
}

3.2.2 自定义ssl的sni

Server Name Indication (SNI) 是 TLS 协议(以前称为 SSL 协议)的扩展,该协议在 HTTPS 中使用。它包含在 TLS/SSL 握手流程中,以确保客户端设备能够看到他们尝试访问的网站的正确 SSL 证书。该扩展使得可以在 TLS 握手期间指定网站的主机名或域名 ,而不是在握手之后打开 HTTP 连接时指定。

services
    .AddHttpMessageHandlerFactory("App")
    .AddSslSniProvider<CustomSslSniProvider>();
sealed class CustomSslSniProvider : SslSniProvider
{
    public override ValueTask<string> GetSslSniAsync(string host, CancellationToken cancellationToken)
    {
        return ValueTask.FromResult(string.Empty);
    }

    public override bool RemoteCertificateValidationCallback(string host, X509Certificate? cert, X509Chain? chain, SslPolicyErrors errors)
    {
        return true;
    }
}

4 两个库的场景选择

无/固定代理 动态代理 客户端 转发端
Microsoft.Extensions.Http 适合 不适合 非常适合 功能弱
HttpMessageHandlerFactory 适合 适合 功能弱 非常适合

HttpMessageHandlerFactory的源代码在https://github.com/xljiulang/HttpMessageHandlerFactory,其功能单一代码量相对Microsoft.Extensions.Http要少一些,阅读其代码之后去理解Microsoft.Extensions.Http会更容易很多。

标签:Http,HttpMessageHandlerFactory,工厂,Extensions,dotnet,return,Microsoft,客户端
From: https://www.cnblogs.com/kewei/p/17419698.html

相关文章

  • httpd2.4 配置https访问
    httpd版本:Serverversion:Apache/2.4.37(AlibabaCloudLinux) 实验步骤如下:1.购买域名,使用阿里云域名购买k.com。2.购买ECS服务器(使用突发式实例-印度尼西亚,便宜3分钱一小时),带有公网IP。3.配置域名解析demo.k.com指向ECS公网IP。4.购买SSL证书,使用阿里云数字证书......
  • xxxxhttps://blog.csdn.net/holecloud/article/details/80139297
    #include"stdafx.h"#include<opencv2\imgproc\imgproc.hpp>#include<windows.h>#include<opencv2/opencv.hpp>#include<cmath>#include<iostream>//#include"DetectPackage.h"#include<cmath>usin......
  • HttpUrlConnection底层实现和关于java host绑定ip即时生效的设置及分析
     最近有个需求需要对于获取URL页面进行host绑定并且立即生效,在java里面实现可以用代理服务器来实现:因为在测试环境下可能需要通过绑定来访问测试环境的应用实现代码如下: publicstaticStringgetResponseText(StringqueryUrl,Stringhost,Stringip){//queryUrl,完整的u......
  • 解决Anroid7.0以上版本无法抓取微信浏览器中Https请求
    为什么安卓7.0以上的系统,微信7.0版本以上无法抓取https包?原因:1.安卓7.0之后,提高了系统安全性。APP默认不信任用户域的证书2.微信7.0以后更新了安全机制,加入了防止中间人attack的机制详情可搜索sslpinning了解防止中间人attackSSLPinninghttps的网站使用使用伪证书可以抓到,但app......
  • 关于RPC和HTTP的理解
    RPC(RemoteProcedureCall,远程过程调用)和HTTP(HypertextTransferProtocol,超文本传输协议)是两种不同的通信协议,用于在计算机网络中实现不同系统之间的通信和数据交换。RPC(远程过程调用):RPC是一种通信机制,允许一个程序调用另一个运行在不同地址空间的程序或服务的方法(即远程过......
  • HTTP 响应状态码
    状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误。这一期我们就来总结一下HTTP状态码。HTTP状态码分为5类:状态码类别原因短语1XXInformational(信息性状态码)接收的请求正在处理2XXSuccessful(......
  • git 连接方式SSH、https方式相互切换
    1、gitremote-v  --查看当前是ssh还是https方式连接2、从ssh切换至httpsgitremoteset-urloriginhttps://xxxx.git(复制仓库https连接)3、从https方式切换至sshgitremoteset-urlorigingit@/xxxxx.git(复制仓库ssh连接) ......
  • 如何挑选合适的海外HTTP代理?海外IP哪家强
    不整虚的,简单粗暴看这些海外HTTP代理服务商的官网就好了:以最基础的量去随便搜常见的那几家就行啦。大家熟知的bright data,得500美元一个月,相当于11.48美元/G,换成现在的汇率,得80.7元/G了。ipidea属于充值模式:1000元/月,动态数据中心IP的话,是15元/GB。netnut是100美元/月使用100GB,也......
  • servJump extends HttpServlet //request.getRequestDispatcher //response.sendRed
    packagecom.test;importjava.io.IOException;importjava.io.PrintWriter;importjava.util.HashMap;importjava.util.Map;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;impo......
  • Fiddler抓包工具安装HTTPS证书
    安装好之后,打开Fiddler根目录,打开CMD执行以下内容makecert.exe-r-ssmy-n"CN=DO_NOT_TRUST_FiddlerRoot,O=DO_NOT_TRUST,OU=Createdbyhttp://www.fiddler2.com"-skysignature-eku1.3.6.1.5.5.7.3.1-h1-cyauthority-asha1-m120-b09/11/2022注意上面命令中,最后......