using System.Net; using LittleShop.Client.Configuration; using LittleShop.Client.Http; using LittleShop.Client.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace LittleShop.Client.Extensions; public static class ServiceCollectionExtensions { public static IServiceCollection AddLittleShopClient( this IServiceCollection services, Action? configureOptions = null, bool useTorProxy = false, string torSocksHost = "127.0.0.1", int torSocksPort = 9050) { // Configure options if (configureOptions != null) { services.Configure(configureOptions); } else { services.Configure(options => { }); } // Register HTTP handlers services.AddTransient(); services.AddTransient(); // Helper function to configure SOCKS5 proxy if TOR is enabled Func createHandler = (serviceProvider) => { if (useTorProxy) { var loggerFactory = serviceProvider.GetRequiredService(); var logger = loggerFactory.CreateLogger("LittleShop.Client.TorProxy"); var proxyUri = $"socks5://{torSocksHost}:{torSocksPort}"; logger.LogInformation("LittleShop.Client: Configuring SOCKS5 proxy at {ProxyUri}", proxyUri); return new SocketsHttpHandler { Proxy = new WebProxy(proxyUri) { BypassProxyOnLocal = false, UseDefaultCredentials = false }, UseProxy = true, AllowAutoRedirect = false, PooledConnectionLifetime = TimeSpan.FromMinutes(5), PooledConnectionIdleTimeout = TimeSpan.FromMinutes(2) }; } else { return new SocketsHttpHandler(); } }; // Register main HTTP client services.AddHttpClient((serviceProvider, client) => { var options = serviceProvider.GetRequiredService>().Value; client.BaseAddress = new Uri(options.BaseUrl); client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds); client.DefaultRequestHeaders.Add("Accept", "application/json"); }) .ConfigurePrimaryHttpMessageHandler(createHandler) .AddHttpMessageHandler() .AddHttpMessageHandler(serviceProvider => { var logger = serviceProvider.GetRequiredService>(); var options = serviceProvider.GetRequiredService>().Value; return new RetryPolicyHandler(logger, options.MaxRetryAttempts); }); services.AddHttpClient((serviceProvider, client) => { var options = serviceProvider.GetRequiredService>().Value; client.BaseAddress = new Uri(options.BaseUrl); client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds); client.DefaultRequestHeaders.Add("Accept", "application/json"); }) .ConfigurePrimaryHttpMessageHandler(createHandler) .AddHttpMessageHandler() .AddHttpMessageHandler(serviceProvider => { var logger = serviceProvider.GetRequiredService>(); var options = serviceProvider.GetRequiredService>().Value; return new RetryPolicyHandler(logger, options.MaxRetryAttempts); }); services.AddHttpClient((serviceProvider, client) => { var options = serviceProvider.GetRequiredService>().Value; client.BaseAddress = new Uri(options.BaseUrl); client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds); client.DefaultRequestHeaders.Add("Accept", "application/json"); }) .ConfigurePrimaryHttpMessageHandler(createHandler) .AddHttpMessageHandler() .AddHttpMessageHandler(serviceProvider => { var logger = serviceProvider.GetRequiredService>(); var options = serviceProvider.GetRequiredService>().Value; return new RetryPolicyHandler(logger, options.MaxRetryAttempts); }); services.AddHttpClient((serviceProvider, client) => { var options = serviceProvider.GetRequiredService>().Value; client.BaseAddress = new Uri(options.BaseUrl); client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds); client.DefaultRequestHeaders.Add("Accept", "application/json"); }) .ConfigurePrimaryHttpMessageHandler(createHandler) .AddHttpMessageHandler() .AddHttpMessageHandler(serviceProvider => { var logger = serviceProvider.GetRequiredService>(); var options = serviceProvider.GetRequiredService>().Value; return new RetryPolicyHandler(logger, options.MaxRetryAttempts); }); services.AddHttpClient((serviceProvider, client) => { var options = serviceProvider.GetRequiredService>().Value; client.BaseAddress = new Uri(options.BaseUrl); client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds); client.DefaultRequestHeaders.Add("Accept", "application/json"); }) .ConfigurePrimaryHttpMessageHandler(createHandler) .AddHttpMessageHandler() .AddHttpMessageHandler(serviceProvider => { var logger = serviceProvider.GetRequiredService>(); var options = serviceProvider.GetRequiredService>().Value; return new RetryPolicyHandler(logger, options.MaxRetryAttempts); }); // Register the main client services.AddScoped(); return services; } public static IServiceCollection AddLittleShopClient( this IServiceCollection services, string baseUrl) { return services.AddLittleShopClient(options => { options.BaseUrl = baseUrl; }); } }