静态 HttpClient 需要来自 app.settings 的 URI
Static HttpClient needs a URI from app.settings
我遇到了类似下面代码的情况。假设我无法注入 IConfiguration 或 IOptions,我如何从 app.settings 获取代理 URI,因为在 class 的实例化发生时静态 HttpClient 属性 已经存在?
public class SomeApiClient : ISomeApiClient
{
private static readonly HttpClientHandler ProxyClientHandler = new HttpClientHandler
{
Proxy = new WebProxy("http://serviceproxy.com"), //TODO Fetch from settings
UseProxy = true,
};
//HttpClient is disposable but should be used liked this
//(https://docs.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-improper-instantiation-antipattern)
private static readonly HttpClient RestClient = new HttpClient(ProxyClientHandler);
//The rest of the non-static class goes here...
}
好的,所以最终的实现是这样的:
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHttpClient<IApiClient, ApiClient>().ConfigurePrimaryHttpMessageHandler(() =>
{
var serviceProxy = new ServiceProxy();
hostContext.Configuration.GetSection("ServiceProxy").Bind(serviceProxy);
var handler = new HttpClientHandler
{
Proxy = new WebProxy(serviceProxy.Uri),
UseProxy = true,
};
return handler;
});
services.AddOptions();
services.Configure<PollingIntervals>(hostContext.Configuration.GetSection("PollingIntervals"));
services.AddHostedService<DownloadWorker>();
services.AddHostedService<ArchiveWorker>();
ConfigureDependencyInjection(services);
});
'typed client' 是这样的:
public class ApiClient : IApiClient
{
private readonly IConfiguration config;
private readonly ILogger<ApiClient> logger;
private readonly HttpClient httpClient;
public ApiClient(
HttpClient httpClient,
IConfiguration config,
ILogger<ApiClient> logger)
{
this.config = config;
this.logger = logger;
this.httpClient = httpClient;
this.httpClient.DefaultRequestHeaders.Clear();
this.httpClient.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
}
有趣的是,我现在收到了大量关于我以前没有收到的实际 HTTP 请求的日志记录。我添加了日志过滤器来调整:
.ConfigureLogging(logging =>
{
//Added these filters to stop seeing too many details about Http requests/responses
logging.AddFilter("System.Net.Http.HttpClient.IApiClient.ClientHandler", LogLevel.Warning);
logging.AddFilter("System.Net.Http.HttpClient.IApiClient.LogicalHandler", LogLevel.Warning);
});
我遇到了类似下面代码的情况。假设我无法注入 IConfiguration 或 IOptions,我如何从 app.settings 获取代理 URI,因为在 class 的实例化发生时静态 HttpClient 属性 已经存在?
public class SomeApiClient : ISomeApiClient
{
private static readonly HttpClientHandler ProxyClientHandler = new HttpClientHandler
{
Proxy = new WebProxy("http://serviceproxy.com"), //TODO Fetch from settings
UseProxy = true,
};
//HttpClient is disposable but should be used liked this
//(https://docs.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-improper-instantiation-antipattern)
private static readonly HttpClient RestClient = new HttpClient(ProxyClientHandler);
//The rest of the non-static class goes here...
}
好的,所以最终的实现是这样的:
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHttpClient<IApiClient, ApiClient>().ConfigurePrimaryHttpMessageHandler(() =>
{
var serviceProxy = new ServiceProxy();
hostContext.Configuration.GetSection("ServiceProxy").Bind(serviceProxy);
var handler = new HttpClientHandler
{
Proxy = new WebProxy(serviceProxy.Uri),
UseProxy = true,
};
return handler;
});
services.AddOptions();
services.Configure<PollingIntervals>(hostContext.Configuration.GetSection("PollingIntervals"));
services.AddHostedService<DownloadWorker>();
services.AddHostedService<ArchiveWorker>();
ConfigureDependencyInjection(services);
});
'typed client' 是这样的:
public class ApiClient : IApiClient
{
private readonly IConfiguration config;
private readonly ILogger<ApiClient> logger;
private readonly HttpClient httpClient;
public ApiClient(
HttpClient httpClient,
IConfiguration config,
ILogger<ApiClient> logger)
{
this.config = config;
this.logger = logger;
this.httpClient = httpClient;
this.httpClient.DefaultRequestHeaders.Clear();
this.httpClient.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
}
有趣的是,我现在收到了大量关于我以前没有收到的实际 HTTP 请求的日志记录。我添加了日志过滤器来调整:
.ConfigureLogging(logging =>
{
//Added these filters to stop seeing too many details about Http requests/responses
logging.AddFilter("System.Net.Http.HttpClient.IApiClient.ClientHandler", LogLevel.Warning);
logging.AddFilter("System.Net.Http.HttpClient.IApiClient.LogicalHandler", LogLevel.Warning);
});