Reputation: 337
what exactly I want :
public static CustomDnsResolver : Dns
{
.....
}
public static void Main(string[] args)
{
var httpClient = new HttpClient();
httpClient.Dns(new CustomDnsResolver());
}
basically I just want to use my custom DNS resolver in HttpClient instead of System default, Is there any way to achieve it?
Upvotes: 12
Views: 9149
Reputation: 4302
The use case you have is exactly why Microsoft build the HttpClient stack. It allow you to put your business logic in layered class with the help of HttpMessageHandler
class. You can find some sample in ms docs or visualstudiomagazine
async Task Main()
{
var dnsHandler = new DnsHandler(new CustomDnsResolver());
var client = new HttpClient(dnsHandler);
var html = await client.GetStringAsync("http://google.com");
}
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";
}
}
async Task Main()
{
var dnsResolver = new CustomDnsResolver();
var sockerHttpHandler = new SocketsHttpHandler()
{
ConnectCallback = async (context, cancellationToken) =>
{
var ipAddress = dnsResolver.Resolve(context.DnsEndPoint.Host);
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp)
{
// Turn off Nagle's algorithm since it degrades
// performance in most HttpClient scenarios.
NoDelay = true
};
try
{
await socket.ConnectAsync(
ipAddress,
context.DnsEndPoint.Port,
cancellationToken);
return new NetworkStream(socket, ownsSocket: true);
}
catch
{
socket.Dispose();
throw;
}
},
};
var client = new HttpClient(sockerHttpHandler);
var html = await client.GetStringAsync("https://google.com");
}
public class CustomDnsResolver
{
public IPAddress Resolve(string host)
{
return IPAddress.Parse("216.58.214.164");
}
}
Upvotes: 10
Reputation: 449
Not sure if this works for all cases, but it worked brilliantly for my case, even when using HTTPS. So what you do is you replace the host in the URL with the actual IP-address that your custom resolver has resolved, and then you simply add a "host" header with the host name. Like this:
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);
I hope this helps as this is far by the first time I've run into this issue and I've never been able to solve it before now.
Upvotes: 10