Hi,
I would like to suppress the exception generated by HttpClient for untrusted certificates. See this StackOverflow post.
My use case is when I am using an internal local host that has a self signed certificate. Currently this generates the following exception stack trace:
Flurl.Http.FlurlHttpException
HResult=0x80131500
Message=Call failed. An error occurred while sending the request. GET https://localhost/abpscripts/getscripts
Source=Flurl.Http
StackTrace:
at Flurl.Http.FlurlRequest.d__23.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Flurl.Http.FlurlRequest.d__19.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Flurl.Http.FlurlRequest.d__19.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Flurl.Http.HttpResponseMessageExtensions.d__3.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapExceptionTResultInner Exception 1:
HttpRequestException: An error occurred while sending the request.Inner Exception 2:
WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.Inner Exception 3:
AuthenticationException: The remote certificate is invalid according to the validation procedure.
How can I configure Flurl so that I can successfully call an end point that is protected by an untrusted certificate?
Flurl uses HttpClient under the hood, so the same Stack Overflow answers apply. The "quick and dirty" (and popular) answer should work as-is. Most of the other answers involve a configuring a handler, which you can plug into Flurl with a custom factory that overrides CreateMessageHandler().
I'm going to close this since it was submitted as a feature request. Generally I prefer to have people post programming questions on Stack Overflow, and feel free to post it there if you need a more in-depth answer, but hopefully this info points you in the right direction.
@tmenier, it took me a bit to make this work. I feel like a little addition to the docs might help. Are they also on GitHub? Taking pull requests?
To be honest, I think it's probably a bit too obscure to add to the docs specifically. This list of different scenarios that can be accommodated with HttpClient by configuring the message handler is huge, and a custom factory is always the hook you need to do it in Flurl.
I always appreciate the offers to add things like this to the docs, but lately I've been steering people toward posting a self-answered Stack Overflow question, which is encouraged, will get much better visibility, and is a better fit since it's solving a very specific programming problem.
How about a samples/examples that show things that "are not to make it into the code". @rellis-of-rhindleton If you have some code to share I would appreciate it.
I seem to hit all the obscure cases :)
But point taken, it is a rather esoteric thing.
I was just thinking that the developer who's looking to customize the HttpClientHandler that Flurl, by default, generates an HttpClientHandler as the HttpMessageHandler, so yes CreateMessageHandler is the place to look. I was wondering why you pointed someone at CreateMessageHandler since HttpMessageHandler doesn't have any such features. Had to look through the Flurl source to figure it out, but now that I know, I'll never need to figure it out again, and someone who already knew a bit more about HttpMessageHandler/HttpClientHandler probably wouldn't need the extra help in the first place.
@natiki -- This is what I wound up with. Could tweak to make an "insert customizations here" example, if desired.
public class CustomHttpClientFactory : DefaultHttpClientFactory
{
public override HttpMessageHandler CreateMessageHandler()
{
var httpMessageHandler = base.CreateMessageHandler();
// By default, Flurl creates HttpClientHandlers as message handlers.
// Confirm this is what it did, and then attach a custom behavior.
if (httpMessageHandler is HttpClientHandler httpClientHandler)
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
}
else
{
_logger.Warn("HttpMessageHandler is type {MessageHandlerType}. Cannot set custom certification validation callback.",
httpMessageHandler.GetType().Name);
}
return httpMessageHandler;
}
}
This issue here on GitHub was what eventually led me to the solution. If it'd be clearer as a Stack Overflow answer then I guess that can be arranged.
Most helpful comment
I seem to hit all the obscure cases :)
But point taken, it is a rather esoteric thing.
I was just thinking that the developer who's looking to customize the HttpClientHandler that Flurl, by default, generates an HttpClientHandler as the HttpMessageHandler, so yes CreateMessageHandler is the place to look. I was wondering why you pointed someone at CreateMessageHandler since HttpMessageHandler doesn't have any such features. Had to look through the Flurl source to figure it out, but now that I know, I'll never need to figure it out again, and someone who already knew a bit more about HttpMessageHandler/HttpClientHandler probably wouldn't need the extra help in the first place.
@natiki -- This is what I wound up with. Could tweak to make an "insert customizations here" example, if desired.
This issue here on GitHub was what eventually led me to the solution. If it'd be clearer as a Stack Overflow answer then I guess that can be arranged.