我有Asp.Net Core WebApi。我正在根据HttpClientFactory pattern进行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);
...
}
}我想实现通过动态代理发送请求。这基本上意味着我可能需要在每次请求时更改代理。到目前为止,我发现了两种方法,没有一种对我来说是好的:
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
};
});
...
}但在这种方法中,每个服务只能有一个代理。
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);
...
}但在这种情况下,我违反了HttpClientFactory模式,并且可能会导致应用程序性能出现问题,如下面的article所述
有没有第三种方法可以动态地更改代理,而不需要重新创建HttpClient
发布于 2019-04-08 21:18:45
实例化后,无法更改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
};
});
...然后:
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);
...
}
}发布于 2020-01-10 01:16:20
我可以通过继承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);
}}
然后我在IoC中注册我的ProxyHttpHandler和ProxyOptions:
public IForksCoreConfigurationBuilder ConfigureProxy(Action<ProxyOptions> options)
{
Services.AddOptions<ProxyOptions>().Configure(options);
Services.AddTransient<ProxyHttpHandler>();
Services.AddHttpClient<IService, MyService>()
.ConfigurePrimaryHttpMessageHandler<ProxyHttpHandler>();
return this;
}https://stackoverflow.com/questions/55574091
复制相似问题