Having dynamic proxy with HttpClientFactory implementation

后端 未结 2 1677
轮回少年
轮回少年 2021-01-06 08:15

I have Asp.Net Core WebApi. I am making Http requests according to HttpClientFactory pattern. Here is my sample code:

public void ConfigureServ         


        
相关标签:
2条回答
  • 2021-01-06 08:46

    I can do that by inheriting from HttpClientHandler:

    public class ProxyHttpHandler : HttpClientHandler
    {
        private int currentProxyIndex = 0;
    
    private ProxyOptions proxyOptions;
    
    public ProxyHttpHandler(IOptions<ProxyOptions> options)
    {
        proxyOptions = options != null ? options.Value : throw new ArgumentNullException(nameof(options));
        UseProxy = true;
    }
    
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var proxy = proxyOptions.Proxies[currentProxyIndex];
        var proxyResolver = new WebProxy(proxy.Host, proxy.Port)
        {
            Credentials = proxy.Credentials
        };
    
        Proxy = proxyResolver;
    
        currentProxyIndex++;
        if(currentProxyIndex >= proxyOptions.Proxies.Count)
            currentProxyIndex = 0;
    
        return base.SendAsync(request, cancellationToken);
    }
    

    }

    Then I register my ProxyHttpHandler and ProxyOptions in IoC:

    public IForksCoreConfigurationBuilder ConfigureProxy(Action<ProxyOptions> options)
    {
        Services.AddOptions<ProxyOptions>().Configure(options);
        Services.AddTransient<ProxyHttpHandler>();
        Services.AddHttpClient<IService, MyService>()
                .ConfigurePrimaryHttpMessageHandler<ProxyHttpHandler>();
    
        return this;
    }
    
    0 讨论(0)
  • 2021-01-06 08:47

    There is no way to change the any of the properties of HttpClientHandler or to assign a new version of HttpClientHandler to an existing HttpClient after it is instantiated. As such, it is then impossible to have a dynamic proxy for a particular HttpClient: you can only specify one proxy.

    The correct way to achieve this is to use named clients, instead, and define a client for each proxy endpoint. Then, you'll need to inject IHttpClientFactory and pick one of the proxies to use, requesting the named client that implements that.

    services.AddHttpClient("MyServiceProxy1").ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new HttpClientHandler
        {
            Proxy = new WebProxy("http://127.0.0.1:8888"),
            UseProxy = true
        };
    });
    
    services.AddHttpClient("MyServiceProxy2").ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new HttpClientHandler
        {
            Proxy = new WebProxy("http://127.0.0.1:8889"),
            UseProxy = true
        };
    });
    
    ...
    

    Then:

    public class MyService : IMyInterface
    {
        private readonly HttpClient _client;
    
        public MyService(IHttpClientFactory httpClientFactory)
        {
            _client = httpClientFactory.CreateClient("MyServiceProxy1");
        }
    
        public async Task CallHttpEndpoint()
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "www.customUrl.com");
            var response = await _client.SendAsync(request);
            ...
        }
    }
    
    0 讨论(0)
提交回复
热议问题