public Action <HttpMessageHandlerBuilder> Configure(Action <HttpMessageHandlerBuilder> next)
        {
            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            return((builder) =>
            {
                // Run other configuration first, we want to decorate.
                next(builder);

                string loggerName = !string.IsNullOrEmpty(builder.Name) ? builder.Name : "Default";

                // We want all of our logging message to show up as-if they are coming from HttpClient,
                // but also to include the name of the client for more fine-grained control.
                ILogger outerLogger = _loggerFactory.CreateLogger($"System.Net.Http.HttpClient.{loggerName}.LogicalHandler");
                ILogger innerLogger = _loggerFactory.CreateLogger($"System.Net.Http.HttpClient.{loggerName}.ClientHandler");

                HttpClientFactoryOptions options = _optionsMonitor.Get(builder.Name);

                // The 'scope' handler goes first so it can surround everything.
                builder.AdditionalHandlers.Insert(0, new LoggingScopeHttpMessageHandler(outerLogger, options));

                // We want this handler to be last so we can log details about the request after
                // service discovery and security happen.
                builder.AdditionalHandlers.Add(new LoggingHttpMessageHandler(innerLogger, options));
            });
        }
Example #2
0
        // Internal for tests
        internal ActiveHandlerTrackingEntry CreateHandlerEntry(string name)
        {
            IServiceProvider services = _services;
            var scope = (IServiceScope?)null;

            HttpClientFactoryOptions options = _optionsMonitor.Get(name);

            if (!options.SuppressHandlerScope)
            {
                scope    = _scopeFactory.CreateScope();
                services = scope.ServiceProvider;
            }

            try
            {
                HttpMessageHandlerBuilder builder = services.GetRequiredService <HttpMessageHandlerBuilder>();
                builder.Name = name;

                // This is similar to the initialization pattern in:
                // https://github.com/aspnet/Hosting/blob/e892ed8bbdcd25a0dafc1850033398dc57f65fe1/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs#L188
                Action <HttpMessageHandlerBuilder> configure = Configure;
                for (int i = _filters.Length - 1; i >= 0; i--)
                {
                    configure = _filters[i].Configure(configure);
                }

                configure(builder);

                // Wrap the handler so we can ensure the inner handler outlives the outer handler.
                var handler = new LifetimeTrackingHttpMessageHandler(builder.Build());

                // Note that we can't start the timer here. That would introduce a very very subtle race condition
                // with very short expiry times. We need to wait until we've actually handed out the handler once
                // to start the timer.
                //
                // Otherwise it would be possible that we start the timer here, immediately expire it (very short
                // timer) and then dispose it without ever creating a client. That would be bad. It's unlikely
                // this would happen, but we want to be sure.
                return(new ActiveHandlerTrackingEntry(name, handler, scope, options.HandlerLifetime));

                void Configure(HttpMessageHandlerBuilder b)
                {
                    for (int i = 0; i < options.HttpMessageHandlerBuilderActions.Count; i++)
                    {
                        options.HttpMessageHandlerBuilderActions[i](b);
                    }
                }
            }
            catch
            {
                // If something fails while creating the handler, dispose the services.
                scope?.Dispose();
                throw;
            }
        }
Example #3
0
        public HttpClient CreateClient(string name)
        {
            ThrowHelper.ThrowIfNull(name);

            HttpMessageHandler handler = CreateHandler(name);
            var client = new HttpClient(handler, disposeHandler: false);

            HttpClientFactoryOptions options = _optionsMonitor.Get(name);

            for (int i = 0; i < options.HttpClientActions.Count; i++)
            {
                options.HttpClientActions[i](client);
            }

            return(client);
        }
        public HttpClient CreateClient(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            HttpMessageHandler handler = CreateHandler(name);
            var client = new HttpClient(handler, disposeHandler: false);

            HttpClientFactoryOptions options = _optionsMonitor.Get(name);

            for (int i = 0; i < options.HttpClientActions.Count; i++)
            {
                options.HttpClientActions[i](client);
            }

            return(client);
        }