是否可以在 C# 的 HttpClient 中设置自定义 DNS 解析器

Is it possible to set custom DNS resolver in C#'s HttpClient

我到底想要什么:

public static CustomDnsResolver : Dns 
{
   .....
}

public static void Main(string[] args) 
{
    var httpClient = new HttpClient();
    httpClient.Dns(new CustomDnsResolver());
}

基本上我只是想在 HttpClient 中使用我的自定义 DNS 解析器而不是系统默认解析器,有什么方法可以实现吗?

您的用例正是 Microsoft 构建 HttpClient 堆栈的原因。它允许您在 HttpMessageHandler class 的帮助下将业务逻辑分层 class。您可以在 ms docs or visualstudiomagazine

中找到一些示例
void Main()
{
    var dnsHandler = new DnsHandler(new CustomDnsResolver());
    var client = new HttpClient(dnsHandler);
    var html = client.GetStringAsync("http://google.com").Result;
}

public class DnsHandler : HttpClientHandler
{
    private readonly CustomDnsResolver _dnsResolver;

    public DnsHandler(CustomDnsResolver dnsResolver)
    {
        _dnsResolver = dnsResolver;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var host = request.RequestUri.Host;
        var ip = _dnsResolver.Resolve(host);

        var builder = new UriBuilder(request.RequestUri);
        builder.Host = ip;

        request.RequestUri = builder.Uri;

        return base.SendAsync(request, cancellationToken);
    }
}

public class CustomDnsResolver
{
    public string Resolve(string host)
    {
        return "127.0.0.1";
    }
}

考虑使用 SocketsHttpHandler.ConnectCallback

不确定这是否适用于所有情况,但它对我的情况非常有效,即使在使用 HTTPS 时也是如此。因此,您要做的是将 URL 中的主机替换为您的自定义解析器已解析的实际 IP-address,然后只需添加一个带有主机名的“主机”header。像这样:

        var requestUri = new Uri("https://123.123.123.123/some/path");
        using var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
        request.Headers.TryAddWithoutValidation("host", "www.host-name.com");
        using var response = await httpClient.SendAsync(request);

我希望这会有所帮助,因为这是我第一次 运行 解决这个问题,而且我以前从未能够解决它。