首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过HttpClientFactory实现动态代理

通过HttpClientFactory实现动态代理
EN

Stack Overflow用户
提问于 2019-04-08 20:59:47
回答 2查看 3K关注 0票数 8

我有Asp.Net Core WebApi。我正在根据HttpClientFactory pattern进行Http请求。下面是我的示例代码:

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddHttpClient<IMyInterface, MyService>();
    ...
}

public class MyService: IMyInterface
{
    private readonly HttpClient _client;

    public MyService(HttpClient client)
    {
        _client = client;
    }

    public async Task CallHttpEndpoint()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, "www.customUrl.com");
        var response = await _client.SendAsync(request);
        ...
    }

}

我想实现通过动态代理发送请求。这基本上意味着我可能需要在每次请求时更改代理。到目前为止,我发现了两种方法,没有一种对我来说是好的:

1.有一个像这样的静态代理:

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddHttpClient<IMyInterface, MyService>().ConfigurePrimaryHttpMessageHandler(() =>
        {
            return new HttpClientHandler
            {
                Proxy = new WebProxy("http://127.0.0.1:8888"),
                UseProxy = true
            };
        });
    ...
}

但在这种方法中,每个服务只能有一个代理。

2.对每个请求处理HttpClient

代码语言:javascript
复制
    HttpClientHandler handler = new HttpClientHandler()
    {
        Proxy = new WebProxy("http://127.0.0.1:8888"),
        UseProxy = true,
    };

    using(var client = new HttpClient(handler))
    {
        var request = new HttpRequestMessage(HttpMethod.Get, "www.customUrl.com");
        var response = await client.SendAsync(request);
        ...
    }

但在这种情况下,我违反了HttpClientFactory模式,并且可能会导致应用程序性能出现问题,如下面的article所述

有没有第三种方法可以动态地更改代理,而不需要重新创建HttpClient

EN

回答 2

Stack Overflow用户

发布于 2019-04-08 21:18:45

实例化后,无法更改HttpClientHandler的任何属性,也无法将新版本的HttpClientHandler分配给现有的HttpClient。因此,不可能为特定的HttpClient指定动态代理:您只能指定一个代理。

实现这一点的正确方法是使用命名客户端,并为每个代理端点定义一个客户端。然后,您将需要注入IHttpClientFactory并选择要使用的代理之一,请求实现该代理的指定客户端。

代码语言:javascript
复制
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
    };
});

...

然后:

代码语言:javascript
复制
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);
        ...
    }
}
票数 9
EN

Stack Overflow用户

发布于 2020-01-10 01:16:20

我可以通过继承HttpClientHandler来实现:

代码语言:javascript
复制
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);
}

}

然后我在IoC中注册我的ProxyHttpHandlerProxyOptions

代码语言:javascript
复制
public IForksCoreConfigurationBuilder ConfigureProxy(Action<ProxyOptions> options)
{
    Services.AddOptions<ProxyOptions>().Configure(options);
    Services.AddTransient<ProxyHttpHandler>();
    Services.AddHttpClient<IService, MyService>()
            .ConfigurePrimaryHttpMessageHandler<ProxyHttpHandler>();

    return this;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55574091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档