具有HttpClientFactory实现的动态代理

Ram*_*nas 4 c# dotnet-httpclient asp.net-core

我有Asp.Net Core WebApi。我正在根据HttpClientFactory模式发出Http请求。这是我的示例代码:

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);
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddHttpClient<IMyInterface, MyService>().ConfigurePrimaryHttpMessageHandler(() =>
        {
            return new HttpClientHandler
            {
                Proxy = new WebProxy("http://127.0.0.1:8888"),
                UseProxy = true
            };
        });
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

2. HttpClient处理每个请求:

    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);
        ...
    }
Run Code Online (Sandbox Code Playgroud)

但是以这种方式,我违反了HttpClientFactory模式,这可能会导致应用程序性能出现问题,如下文所述

有没有第三种方法可以在不重新创建的情况下动态更改代理HttpClient

Chr*_*att 5

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

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

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
    };
});

...
Run Code Online (Sandbox Code Playgroud)

然后:

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);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您事先不知道代理 url 怎么办? (3认同)