🐛 Fix http client didn't ignore CA

This commit is contained in:
2025-12-25 23:20:23 +08:00
parent ded3a70cb7
commit 1c6b324b0d
3 changed files with 112 additions and 106 deletions

View File

@@ -24,127 +24,129 @@ public static class Extensions
private const string HealthEndpointPath = "/health";
private const string AlivenessEndpointPath = "/alive";
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
extension<TBuilder>(TBuilder builder) where TBuilder : IHostApplicationBuilder
{
// Allow unencrypted grpc
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
builder.ConfigureOpenTelemetry();
builder.AddDefaultHealthChecks();
builder.Services.AddServiceDiscovery();
builder.Services.AddServiceDiscoveryCore();
builder.Services.ConfigureHttpClientDefaults(http =>
public TBuilder AddServiceDefaults()
{
// Turn on resilience by default
http.AddStandardResilienceHandler();
// Allow unencrypted grpc
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
// Turn on service discovery by default
http.AddServiceDiscovery();
});
builder.ConfigureOpenTelemetry();
builder.Services.AddSingleton<IClock>(SystemClock.Instance);
builder.AddDefaultHealthChecks();
builder.AddNatsClient("Queue");
builder.AddRedisClient(
"Cache",
configureOptions: opts =>
builder.Services.AddServiceDiscovery();
builder.Services.AddServiceDiscoveryCore();
builder.Services.ConfigureHttpClientDefaults(http =>
{
opts.AbortOnConnectFail = false;
}
);
// Setup cache service
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Cache");
options.InstanceName = "dyson:";
});
builder.Services.AddSingleton<IDistributedLockFactory, RedLockFactory>(sp =>
{
var mux = sp.GetRequiredService<IConnectionMultiplexer>();
return RedLockFactory.Create(new List<RedLockMultiplexer> { new(mux) });
});
builder.Services.AddSingleton<ICacheService, CacheServiceRedis>();
if (builder.Configuration.GetSection("Cache")["Serializer"] == "MessagePack")
builder.Services.AddSingleton<ICacheSerializer, MessagePackCacheSerializer>();
else
builder.Services.AddSingleton<ICacheSerializer, JsonCacheSerializer>();
return builder;
}
public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder
.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
})
.WithTracing(tracing =>
{
tracing
.AddSource(builder.Environment.ApplicationName)
.AddAspNetCoreInstrumentation(tracing =>
// Exclude health check requests from tracing
tracing.Filter = context =>
!context.Request.Path.StartsWithSegments(HealthEndpointPath)
&& !context.Request.Path.StartsWithSegments(AlivenessEndpointPath)
)
.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation();
// Turn on resilience by default
http.AddStandardResilienceHandler();
// Turn on service discovery by default
http.AddServiceDiscovery();
// Ignore CA
http.ConfigurePrimaryHttpMessageHandler(sp => new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (_, _, _, _) => true,
});
});
builder.AddOpenTelemetryExporters();
builder.Services.AddSingleton<IClock>(SystemClock.Instance);
return builder;
}
builder.AddNatsClient("Queue");
builder.AddRedisClient(
"Cache",
configureOptions: opts =>
{
opts.AbortOnConnectFail = false;
}
);
private static TBuilder AddOpenTelemetryExporters<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
var useOtlpExporter = !string.IsNullOrWhiteSpace(
builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]
);
// Setup cache service
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Cache");
});
builder.Services.AddSingleton<IDistributedLockFactory, RedLockFactory>(sp =>
{
var mux = sp.GetRequiredService<IConnectionMultiplexer>();
return RedLockFactory.Create(new List<RedLockMultiplexer> { new(mux) });
});
builder.Services.AddSingleton<ICacheService, CacheServiceRedis>();
if (builder.Configuration.GetSection("Cache")["Serializer"] == "MessagePack")
builder.Services.AddSingleton<ICacheSerializer, MessagePackCacheSerializer>();
else
builder.Services.AddSingleton<ICacheSerializer, JsonCacheSerializer>();
if (useOtlpExporter)
{
builder.Services.AddOpenTelemetry().UseOtlpExporter();
return builder;
}
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
//if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
//{
// builder.Services.AddOpenTelemetry()
// .UseAzureMonitor();
//}
public TBuilder ConfigureOpenTelemetry()
{
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
return builder;
}
builder
.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
})
.WithTracing(tracing =>
{
tracing
.AddSource(builder.Environment.ApplicationName)
.AddAspNetCoreInstrumentation(tracing =>
// Exclude health check requests from tracing
tracing.Filter = context =>
!context.Request.Path.StartsWithSegments(HealthEndpointPath)
&& !context.Request.Path.StartsWithSegments(AlivenessEndpointPath)
)
.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation();
});
public static TBuilder AddDefaultHealthChecks<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder
.Services.AddHealthChecks()
// Add a default liveness check to ensure app is responsive
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
builder.AddOpenTelemetryExporters();
return builder;
return builder;
}
private TBuilder AddOpenTelemetryExporters()
{
var useOtlpExporter = !string.IsNullOrWhiteSpace(
builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]
);
if (useOtlpExporter)
{
builder.Services.AddOpenTelemetry().UseOtlpExporter();
}
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
//if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
//{
// builder.Services.AddOpenTelemetry()
// .UseAzureMonitor();
//}
return builder;
}
public TBuilder AddDefaultHealthChecks()
{
builder
.Services.AddHealthChecks()
// Add a default liveness check to ensure app is responsive
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
return builder;
}
}
public static WebApplication MapDefaultEndpoints(this WebApplication app)