/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with the provided /// <see cref="IAsyncPolicy{HttpResponseMessage}"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="policy">The <see cref="IAsyncPolicy{HttpResponseMessage}"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// </remarks> public static IHttpClientBuilder AddPolicyHandler(this IHttpClientBuilder builder, IAsyncPolicy <HttpResponseMessage> policy) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } builder.AddHttpMessageHandler(() => new PolicyHttpMessageHandler(policy)); return(builder); }
/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with a <see cref="Policy"/> /// created by executing the provided configuration delegate. The policy builder will be preconfigured to trigger /// application of the policy for requests that fail with a connection or server error (5XX status code). /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="configurePolicy">A delegate used to create a <see cref="IAsyncPolicy{HttpResponseMessage}"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// <para> /// The <see cref="PolicyBuilder{HttpResponseMessage}"/> provided to <paramref name="configurePolicy"/> has been /// preconfigured to handle connection errors (as <see cref="HttpRequestException"/>) or server errors (as a 5XX HTTP /// status code). The configuration is similar to the following code sample: /// <code> /// Policy.HandleAsync<HttpRequestException>().OrResult<HttpResponseMessage>(response => /// { /// return response.StatusCode >= HttpStatusCode.InternalServerError; /// } /// </code> /// </para> /// <para> /// The policy created by <paramref name="configurePolicy"/> will be cached indefinitely per named client. Policies /// are generally designed to act as singletons, and can be shared when appropriate. To share a policy across multiple /// named clients, first create the policy and the pass it to multiple calls to /// <see cref="AddPolicyHandler(IHttpClientBuilder, IAsyncPolicy)"/> or /// <see cref="AddPolicyHandler(IHttpClientBuilder, IAsyncPolicy{HttpResponseMessage})"/> as desired. /// </para> /// </remarks> public static IHttpClientBuilder AddServerErrorPolicyHandler( this IHttpClientBuilder builder, Func <PolicyBuilder <HttpResponseMessage>, IAsyncPolicy <HttpResponseMessage> > configurePolicy) { var policyBuilder = Policy.Handle <HttpRequestException>().OrResult <HttpResponseMessage>(response => { return(response.StatusCode >= HttpStatusCode.InternalServerError); }); // Important - cache policy instances so that they are singletons per handler. var policy = configurePolicy(policyBuilder); builder.AddHttpMessageHandler(() => new PolicyHttpMessageHandler(policy)); return(builder); }
public static IHttpClientBuilder AddAuthentication(this IHttpClientBuilder builder, Func <IServiceProvider, ClientCredentials> credentialsProvider, Func <IServiceProvider, string> identityAuthorityProvider) { builder.Services.TryAddSingleton <AccessTokensCacheManager>(); builder.AddHttpMessageHandler(provider => { var credentials = credentialsProvider.Invoke(provider); var identityAuthority = identityAuthorityProvider.Invoke(provider); return(CreateDelegatingHandler(provider, credentials, identityAuthority)); }); return(builder); }
/// <summary> /// Adds the retry handler. /// </summary> /// <param name="builder">The builder.</param> /// <param name="retryPolicyOptions">The retry policy options.</param> /// <returns>IHttpClientBuilder.</returns> /// <exception cref="System.ArgumentNullException">builder</exception> /// <exception cref="System.ArgumentNullException">retryPolicyOptions</exception> public static IHttpClientBuilder AddRetryHandler(this IHttpClientBuilder builder, HttpRetryPolicyOptions retryPolicyOptions) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (retryPolicyOptions == null) { throw new ArgumentNullException(nameof(retryPolicyOptions)); } builder.AddHttpMessageHandler(() => new RetryDelegatingHandler(retryPolicyOptions)); return(builder); }
public static IHttpClientBuilder AddNaosMessageHandlers(this IHttpClientBuilder builder, Action <IHttpClientBuilder> setupAction = null) { if (setupAction != null) { setupAction.Invoke(builder); return(builder); } else { // default handlers return(builder .AddHttpMessageHandler <HttpClientCorrelationHandler>() .AddHttpMessageHandler <HttpClientServiceContextHandler>() .AddHttpMessageHandler <HttpClientLogHandler>()); } }
/// <summary> /// Adds <see cref="HttpRecorderDelegatingHandler"/> as a HttpMessageHandler in the client pipeline. /// </summary> /// <param name="httpClientBuilder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="interactionName"> /// The name of the interaction. /// If you use the default <see cref="IInteractionRepository"/>, this will be the path to the HAR file (relative or absolute) and /// if no file extension is provided, .har will be used. /// </param> /// <param name="mode">The <see cref="HttpRecorderMode" />. Defaults to <see cref="HttpRecorderMode.Auto" />.</param> /// <param name="matcher"> /// The <see cref="IRequestMatcher"/> to use to match interactions with incoming <see cref="HttpRequestMessage"/>. /// Defaults to matching Once by <see cref="HttpMethod"/> and <see cref="HttpRequestMessage.RequestUri"/>. /// <see cref="RulesMatcher.ByHttpMethod"/> and <see cref="RulesMatcher.ByRequestUri"/>. /// </param> /// <param name="repository"> /// The <see cref="IInteractionRepository"/> to use to read/write the interaction. /// Defaults to <see cref="HttpArchiveInteractionRepository"/>. /// </param> /// <param name="anonymizer"> /// The <see cref="IInteractionAnonymizer"/> to use to anonymize the interaction. /// Defaults to <see cref="RulesInteractionAnonymizer.Default"/>. /// </param> /// <returns>The updated <see cref="IHttpClientBuilder"/>.</returns> public static IHttpClientBuilder AddHttpRecorder( this IHttpClientBuilder httpClientBuilder, string interactionName, HttpRecorderMode mode = HttpRecorderMode.Auto, IRequestMatcher matcher = null, IInteractionRepository repository = null, IInteractionAnonymizer anonymizer = null) { var recorder = new HttpRecorderDelegatingHandler( interactionName, mode: mode, matcher: matcher, repository: repository, anonymizer: anonymizer); return(httpClientBuilder.AddHttpMessageHandler((sp) => recorder)); }
/// <summary> /// /// </summary> /// <param name="clientBuilder"></param> /// <param name="accessMethod"></param> /// <param name="tokenEndpoint"></param> /// <param name="clientId"></param> /// <param name="clientSecret"></param> /// <param name="tokenStore"></param> /// <returns></returns> public static void AddOAuth( this IHttpClientBuilder clientBuilder, string accessMethod, string tokenEndpoint, string clientId, string clientSecret, ITokenStore tokenStore) { if (string.IsNullOrEmpty(accessMethod)) { throw new ArgumentNullException(nameof(accessMethod)); } if (string.IsNullOrEmpty(tokenEndpoint)) { throw new ArgumentNullException(nameof(tokenEndpoint)); } if (string.IsNullOrEmpty(clientId)) { throw new ArgumentNullException(nameof(clientId)); } if (string.IsNullOrEmpty(clientSecret)) { throw new ArgumentNullException(nameof(clientSecret)); } if (tokenStore == null) { throw new ArgumentNullException(nameof(tokenStore)); } clientBuilder.Services.AddScoped(_ => tokenStore); clientBuilder.Services.AddScoped(s => { var client = new TokenClient( tokenEndpoint, clientId, clientSecret); return(new IdentityModelTokenClientAdapter(client)); }); clientBuilder.Services.AddScoped(s => { var tokenManager = s.GetRequiredService <ITokenNegotiator>(); return(new AccessTokenDelegatingHandler(tokenManager)); }); clientBuilder.AddHttpMessageHandler <AccessTokenDelegatingHandler>(); }
/// <summary> /// 添加token应用的http消息处理程序 /// </summary> /// <typeparam name="TOAuthTokenHandler"></typeparam> /// <param name="builder"></param> /// <param name="handlerFactory">hanlder的创建委托</param> /// <param name="tokenProviderSearchMode">token提供者的查找模式</param> /// <returns></returns> public static IHttpClientBuilder AddOAuthTokenHandler <TOAuthTokenHandler>(this IHttpClientBuilder builder, Func <IServiceProvider, ITokenProvider, TOAuthTokenHandler> handlerFactory, TypeMatchMode tokenProviderSearchMode = TypeMatchMode.TypeOrBaseTypes) where TOAuthTokenHandler : OAuthTokenHandler { var httpApiType = builder.GetHttpApiType(); if (httpApiType == null) { throw new InvalidOperationException($"无效的{nameof(IHttpClientBuilder)},找不到其关联的http接口类型"); } return(builder.AddHttpMessageHandler(serviceProvider => { var factory = serviceProvider.GetRequiredService <ITokenProviderFactory>(); var tokenProvider = factory.Create(httpApiType, tokenProviderSearchMode); return handlerFactory(serviceProvider, tokenProvider); })); }
/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with the provided /// <see cref="IAsyncPolicy"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="policy">The <see cref="IAsyncPolicy"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// </remarks> public static IHttpClientBuilder AddPolicyHandler(this IHttpClientBuilder builder, IAsyncPolicy policy) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } // Important - cache policy instances so that they are singletons per handler. var innerPolicy = policy.WrapAsync(Policy.NoOpAsync <HttpResponseMessage>()); builder.AddHttpMessageHandler(() => new PolicyHttpMessageHandler(innerPolicy)); return(builder); }
public static IHttpClientBuilder AddAccessTokenPassThrough(this IHttpClientBuilder builder) { builder.Services .AddHttpContextAccessor() .AddPostConfigure <PassThroughTokenHandlerOptions, PostConfigurePassThroughAccessTokenHandlerOptions>(); var instanceName = builder.Name; return(builder.AddHttpMessageHandler(sp => { var optionsMonitor = sp.GetRequiredService <IOptionsMonitor <PassThroughTokenHandlerOptions> >(); var options = optionsMonitor.Get(instanceName); return new PassThroughTokenHandler( sp.GetRequiredService <IHttpContextAccessor>(), options); })); }
public static IHttpClientBuilder SendTraceIdentifiersFromHttpContext(this IHttpClientBuilder builder, Action <HttpRequestMessage, TraceIdentifiersContext> setupIdentifiers = null) { builder.AddHttpMessageHandler(configureHandler: provider => { IHttpContextAccessor httpContextAccessor = provider.GetRequiredService <IHttpContextAccessor>(); TraceIdentifiersContext context = httpContextAccessor.HttpContext.Features.Get <TraceIdentifiersContext>(); if (setupIdentifiers == null) { return(new SendIdentifiersDelegatingHandler(request => request.TryAddLocalSharedAndRemoteShared(context, SendIdentifiersOptions.Default))); } return(new SendIdentifiersDelegatingHandler(request => setupIdentifiers.Invoke(request, context))); }); return(builder); }
/// <summary> /// Adds services required for adding correlation id to each outgoing <see cref="HttpClient"/> request. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/> to add the services to.</param> /// <param name="configureOptions">The action used to configure <see cref="CorrelateClientOptions"/>.</param> /// <returns>The <see cref="IHttpClientBuilder"/> so that additional calls can be chained.</returns> public static IHttpClientBuilder CorrelateRequests(this IHttpClientBuilder builder, Action <CorrelateClientOptions> configureOptions) { builder.Services.AddCorrelate(); builder.Services.TryAddTransient <CorrelatingHttpMessageHandler>(); builder.Services.Configure(builder.Name, configureOptions); builder.AddHttpMessageHandler(s => { var allClientOptions = s.GetRequiredService <IOptionsSnapshot <CorrelateClientOptions> >(); var thisClientOptions = new OptionsWrapper <CorrelateClientOptions>(allClientOptions.Get(builder.Name)); return(ActivatorUtilities.CreateInstance <CorrelatingHttpMessageHandler>( s, (IOptions <CorrelateClientOptions>)thisClientOptions )); }); return(builder); }
public static IHttpClientBuilder AddTransientHttpError(this IHttpClientBuilder httpClient) { return(httpClient .AddHttpMessageHandler <CustomMessageHandler>() .AddTransientHttpErrorPolicy(policy => { //return policy.WaitAndRetryAsync(3, i => //{ // System.Diagnostics.Debug.WriteLine("11212"); // return TimeSpan.FromSeconds(300); //}); return policy.OrResult(response => !response.IsSuccessStatusCode) .WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), // 进行第一次重试之前延时1秒 TimeSpan.FromSeconds(2), // 进行第二次重试之前延时2秒 TimeSpan.FromSeconds(10), }); })); }
public static IHttpClientBuilder RegisterAndAddHttpMessageHandler <T>(this IHttpClientBuilder builder) where T : DelegatingHandler { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.Services.TryAddTransient <T>(); if (!builder.Services.Any(sd => sd.ServiceType == typeof(T) && sd.Lifetime == ServiceLifetime.Transient)) { throw new InvalidOperationException($"An IServiceCollection registration for '{typeof(T).Name}' with the required transient service lifetime was not found and cannot be added."); } builder.AddHttpMessageHandler <T>(); return(builder); }
protected virtual void ConfigureHttpMessageHandlers(string serviceName, IServiceConfig serviceEndpoint, IHttpClientBuilder builder) { var retryPolicy = HttpPolicyExtensions .HandleTransientHttpError() .RetryAsync(TransientErrorRetryCount); var noOp = Policy.NoOpAsync().AsAsyncPolicy <HttpResponseMessage>(); // IMPORTANT: This component should be only dependent on SingleInstance() components. // Transient instances may cause difficulties with tracing side effects raised by their // state or other transient deps (for example, per-request auth). // https://github.com/aspnet/HttpClientFactory/issues/198 // https://github.com/aspnet/Docs/issues/9306 builder .AddHttpMessageHandler <CorrelationIdHandler>() .AddHttpMessageHandler(services => new BearerAccessTokenHandler(services.GetRequiredService <IBearerTokenStorage>(), serviceEndpoint.ExcludeAccessToken)) .AddPolicyHandler(request => request.Method == HttpMethod.Get || request.Method == HttpMethod.Head ? retryPolicy : noOp) .AddHttpMessageHandler <RequestResponseLoggingHandler>(); }
/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with a policy returned /// by the <paramref name="policySelector"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="policySelector"> /// Selects an <see cref="IAsyncPolicy{HttpResponseMessage}"/> to apply to the current request. /// </param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// </remarks> public static IHttpClientBuilder AddPolicyHandler( this IHttpClientBuilder builder, Func <IServiceProvider, HttpRequestMessage, IAsyncPolicy <HttpResponseMessage> > policySelector) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (policySelector == null) { throw new ArgumentNullException(nameof(policySelector)); } builder.AddHttpMessageHandler((services) => { return(new PolicyHttpMessageHandler((request) => policySelector(services, request))); }); return(builder); }
/// <summary> /// Adds the retry handler. /// </summary> /// <param name="builder">The builder.</param> /// <param name="configure">The configure.</param> /// <returns>IHttpClientBuilder.</returns> /// <exception cref="System.ArgumentNullException">builder</exception> /// <exception cref="System.ArgumentNullException">configure</exception> public static IHttpClientBuilder AddRetryHandler(this IHttpClientBuilder builder, Action <HttpRetryPolicyOptions> configure) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (configure == null) { throw new ArgumentNullException(nameof(configure)); } HttpRetryPolicyOptions retryPolicyOptions = new HttpRetryPolicyOptions(); configure(retryPolicyOptions); builder.AddHttpMessageHandler(() => new RetryDelegatingHandler(retryPolicyOptions)); return(builder); }
/// <summary> /// Registers an action to invoke before a <see cref="HttpRequestMessage"/> is sent by calling <see cref="HttpClientBuilderExtensions.AddHttpMessageHandler(IHttpClientBuilder, Func{IServiceProvider, DelegatingHandler})"/>. /// </summary> /// <param name="httpClientBuilder">The HTTP client builder </param> /// <param name="beforeSend">The action to invoke before sending the <see cref="HttpRequestMessage"/>.</param> /// <returns>The <see cref="IHttpClientBuilder"/> to use for further configuration.</returns> public static IHttpClientBuilder ForeachRequest( this IHttpClientBuilder httpClientBuilder, Action <HttpRequestMessage, CancellationToken> beforeSend ) { if (httpClientBuilder == null) { throw new ArgumentNullException(nameof(httpClientBuilder)); } if (beforeSend == null) { throw new ArgumentNullException(nameof(beforeSend)); } httpClientBuilder .AddHttpMessageHandler(serviceProvider => new HttpClientDelegatingHandler( (serviceProvider, request, cancellationToken) => beforeSend.Invoke(request, cancellationToken) )); return(httpClientBuilder); }
/// <summary> /// Adds an additional message handler from the dependency injection container for a named <see cref="HttpClient"/> /// AND registers it in the container with <see cref="ServiceLifetime.Transient"/> service lifetime. /// </summary> /// <typeparam name="THandler">The type of the <see cref="DelegatingHandler"/>.</typeparam> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="implementationFactory">The factory that creates the service, if any.</param> /// <returns>The updated <see cref="IHttpClientBuilder"/>.</returns> public static IHttpClientBuilder AddAndRegisterHttpMessageHandler <THandler>( this IHttpClientBuilder builder, Func <IServiceProvider, THandler> implementationFactory = null) where THandler : DelegatingHandler { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (implementationFactory == null) { builder.Services.TryAddTransient <THandler>(); } else { builder.Services.TryAddTransient(implementationFactory); } return(builder.AddHttpMessageHandler <THandler>()); }
/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with a policy returned /// by the <see cref="IReadOnlyPolicyRegistry{String}"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="policySelector"> /// Selects an <see cref="IAsyncPolicy{HttpResponseMessage}"/> to apply to the current request. /// </param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// </remarks> public static IHttpClientBuilder AddPolicyHandlerFromRegistry( this IHttpClientBuilder builder, Func <IReadOnlyPolicyRegistry <string>, HttpRequestMessage, IAsyncPolicy <HttpResponseMessage> > policySelector) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (policySelector == null) { throw new ArgumentNullException(nameof(policySelector)); } builder.AddHttpMessageHandler((services) => { var registry = services.GetRequiredService <IReadOnlyPolicyRegistry <string> >(); return(new PolicyHttpMessageHandler((request) => policySelector(registry, request))); }); return(builder); }
/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with a <see cref="Policy"/> /// created by executing the provided configuration delegate. The policy builder will be preconfigured to trigger /// application of the policy for requests that fail with conditions that indicate a transient failure. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="configurePolicy">A delegate used to create a <see cref="IAsyncPolicy{HttpResponseMessage}"/>.</param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// <para> /// The <see cref="PolicyBuilder{HttpResponseMessage}"/> provided to <paramref name="configurePolicy"/> has been /// preconfigured errors to handle errors in the following categories: /// <list type="bullet"> /// <item><description>Network failures (as <see cref="HttpRequestException"/>)</description></item> /// <item><description>HTTP 5XX status codes (server errors)</description></item> /// <item><description>HTTP 408 status code (request timeout)</description></item> /// </list> /// </para> /// <para> /// The policy created by <paramref name="configurePolicy"/> will be cached indefinitely per named client. Policies /// are generally designed to act as singletons, and can be shared when appropriate. To share a policy across multiple /// named clients, first create the policy and then pass it to multiple calls to /// <see cref="AddPolicyHandler(IHttpClientBuilder, IAsyncPolicy{HttpResponseMessage})"/> as desired. /// </para> /// </remarks> public static IHttpClientBuilder AddTransientHttpErrorPolicy( this IHttpClientBuilder builder, Func <PolicyBuilder <HttpResponseMessage>, IAsyncPolicy <HttpResponseMessage> > configurePolicy) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (configurePolicy == null) { throw new ArgumentNullException(nameof(configurePolicy)); } var policyBuilder = HttpPolicyExtensions.HandleTransientHttpError(); // Important - cache policy instances so that they are singletons per handler. var policy = configurePolicy(policyBuilder); builder.AddHttpMessageHandler(() => new PolicyHttpMessageHandler(policy)); return(builder); }
/// <summary> /// Registers an action to invoke before a <see cref="HttpRequestMessage"/> is sent by calling <see cref="HttpClientBuilderExtensions.AddHttpMessageHandler(IHttpClientBuilder, Func{IServiceProvider, DelegatingHandler})"/>. /// </summary> /// <param name="httpClientBuilder">The HTTP client builder </param> /// <param name="beforeSend">The action to invoke before sending the <see cref="HttpRequestMessage"/>.</param> /// <returns>The <see cref="IHttpClientBuilder"/> to use for further configuration.</returns> public static IHttpClientBuilder ForeachRequest( this IHttpClientBuilder httpClientBuilder, Action <IServiceProvider, HttpRequestMessage, CancellationToken> beforeSend ) { if (httpClientBuilder == null) { throw new ArgumentNullException(nameof(httpClientBuilder)); } if (beforeSend == null) { throw new ArgumentNullException(nameof(beforeSend)); } httpClientBuilder .AddHttpMessageHandler(serviceProvider => new HttpClientDelegatingHandler( beforeSend, () => serviceProvider.GetService <IHttpContextAccessor>()?.HttpContext?.RequestServices?.GetService <IServiceProvider>() ?? serviceProvider )); return(httpClientBuilder); }
/// <summary> /// Adds a <see cref="PolicyHttpMessageHandler"/> which will surround request execution with a policy returned /// by the <see cref="IReadOnlyPolicyRegistry{String}"/>. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="policyKey"> /// The key used to resolve a policy from the <see cref="IReadOnlyPolicyRegistry{String}"/>. /// </param> /// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns> /// <remarks> /// <para> /// See the remarks on <see cref="PolicyHttpMessageHandler"/> for guidance on configuring policies. /// </para> /// </remarks> public static IHttpClientBuilder AddPolicyHandlerFromRegistry(this IHttpClientBuilder builder, string policyKey) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (policyKey == null) { throw new ArgumentNullException(nameof(policyKey)); } builder.AddHttpMessageHandler((services) => { var registry = services.GetRequiredService <IReadOnlyPolicyRegistry <string> >(); var policy = registry.Get <IAsyncPolicy <HttpResponseMessage> >(policyKey); return(new PolicyHttpMessageHandler(policy)); }); return(builder); }
/// <summary> /// Adds a <see cref="HttpTracingDelegatingHandler"/> to enable tracing of requests/responses. /// </summary> /// <param name="builder">The <see cref="IHttpClientBuilder"/>.</param> /// <param name="categoryName"> /// The category name to use for logging. /// Defaults to "System.Net.Http.HttpClient.{HttpClient.Name}.TraceHandler".</param> /// <param name="isResponseSuccessful"> /// A function to allow customization of the evaluation of a successful response. /// Defaults to <see cref="HttpResponseMessage.IsSuccessStatusCode"/>. /// </param> /// <param name="bufferRequests"> /// When set to true, will actively buffer the requests bodies. /// This is to be used when you want to see the content of requests /// when using serializer that are forward-only. /// This will impact performance and memory consumption, but is probably fine if you are /// in a typical run-of-the-mill scenario. /// </param> /// <param name="logger"> /// Use a custom <see cref="ILogger"/> instead of the one provided by the <see cref="ILoggerFactory"/>. /// When used, the <paramref name="categoryName"/> is ineffective. /// </param> /// <returns>The updated <see cref="IHttpClientBuilder"/>.</returns> public static IHttpClientBuilder AddHttpTracing( this IHttpClientBuilder builder, string categoryName = null, Func <HttpResponseMessage, bool> isResponseSuccessful = null, bool bufferRequests = false, ILogger logger = null) { if (builder is null) { throw new ArgumentNullException(nameof(builder)); } if (string.IsNullOrEmpty(categoryName)) { categoryName = HttpTracingDelegatingHandler.LoggerCategory(builder.Name); } return(builder.AddHttpMessageHandler( sp => new HttpTracingDelegatingHandler( logger: logger ?? sp.GetRequiredService <ILoggerFactory>().CreateLogger(categoryName), isResponseSuccessful: isResponseSuccessful, bufferRequests: bufferRequests))); }
/// <summary> /// Adds a message handler for propagating headers collected by the <see cref="HeaderPropagationMiddleware"/> to a outgoing request, /// explicitly specifying which headers to propagate. /// </summary> /// <remarks>This also allows to redefine the name to use for a header in the outgoing request.</remarks> /// <param name="builder">The <see cref="IHttpClientBuilder"/> to add the message handler to.</param> /// <param name="configure">A delegate used to configure the <see cref="HeaderPropagationMessageHandlerOptions"/>.</param> /// <returns>The <see cref="IHttpClientBuilder"/> so that additional calls can be chained.</returns> public static IHttpClientBuilder AddHeaderPropagation(this IHttpClientBuilder builder, Action <HeaderPropagationMessageHandlerOptions> configure) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (configure == null) { throw new ArgumentNullException(nameof(configure)); } builder.Services.AddHeaderPropagation(); builder.AddHttpMessageHandler(services => { var options = new HeaderPropagationMessageHandlerOptions(); configure(options); return(new HeaderPropagationMessageHandler(options, services.GetRequiredService <HeaderPropagationValues>())); }); return(builder); }
/// <summary> /// Adds a message handler for propagating headers collected by the <see cref="HeaderPropagationMiddleware"/> to a outgoing request. /// </summary> /// <remarks> /// When using this method, all the configured headers will be applied to the outgoing HTTP requests. /// </remarks> /// <param name="builder">The <see cref="IHttpClientBuilder"/> to add the message handler to.</param> /// <returns>The <see cref="IHttpClientBuilder"/> so that additional calls can be chained.</returns> public static IHttpClientBuilder AddHeaderPropagation(this IHttpClientBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.Services.AddHeaderPropagation(); builder.AddHttpMessageHandler(services => { var options = new HeaderPropagationMessageHandlerOptions(); var middlewareOptions = services.GetRequiredService <IOptions <HeaderPropagationOptions> >(); for (var i = 0; i < middlewareOptions.Value.Headers.Count; i++) { var header = middlewareOptions.Value.Headers[i]; options.Headers.Add(header.CapturedHeaderName, header.CapturedHeaderName); } return(new HeaderPropagationMessageHandler(options, services.GetRequiredService <HeaderPropagationValues>())); }); return(builder); }
/// <summary> /// Add logging handler to HttpClient /// </summary> /// <param name="builder"></param> /// <param name="adjustSettings"></param> /// <returns></returns> public static IHttpClientBuilder AddLoggingHandler( this IHttpClientBuilder builder, Action <LoggingHttpHandler.Settings>?adjustSettings = null) { var name = builder.Name; var settings = new LoggingHttpHandler.Settings(); adjustSettings?.Invoke(settings); if (settings.LogBody == null) { throw new ArgumentException($"{nameof(settings.LogBody)} can't be null"); } if (settings.LogLevel == null) { throw new ArgumentException($"{nameof(settings.LogLevel)} can't be null"); } if (settings.LogLevelException == null) { throw new ArgumentException($"{nameof(settings.LogLevelException)} can't be null"); } return(builder.AddHttpMessageHandler(sp => new LoggingHttpHandler(sp.GetRequiredService <ILoggerFactory>(), name, settings))); }
public static IHttpClientBuilder AddDevspacesSupport(this IHttpClientBuilder builder) { builder.AddHttpMessageHandler <DevspacesMessageHandler>(); return(builder); }
/// <summary> /// Adds a delegate handler to audit HttpClient calls. /// </summary> /// <param name="builder">The Microsoft.Extensions.DependencyInjection.IHttpClientBuilder</param> /// <param name="config">The audit configuration</param> /// <returns></returns> public static IHttpClientBuilder AddAuditHandler(this IHttpClientBuilder builder, Action <ConfigurationApi.IAuditClientHandlerConfigurator> config) { return(builder.AddHttpMessageHandler(() => new AuditHttpClientHandler(config, null))); }
/// <summary> /// Adds the user access token handler to an HttpClient /// </summary> /// <param name="httpClientBuilder"></param> /// <returns></returns> public static IHttpClientBuilder AddUserAccessTokenHandler(this IHttpClientBuilder httpClientBuilder) { return(httpClientBuilder.AddHttpMessageHandler <UserAccessTokenHandler>()); }