From bcd5b11f90ae438d31e31e33235efc8a1940782d Mon Sep 17 00:00:00 2001 From: Bolaji Ayodeji Date: Wed, 10 Jul 2024 10:02:42 +0100 Subject: [PATCH 1/4] docs: update UTM on links --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ef3684e..63c8998 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## .NET Core SDK -[![APItoolkit SDK](https://img.shields.io/badge/APItoolkit-SDK-0068ff?logo=dotnet)](https://github.com/topics/apitoolkit-sdk) [![Join Discord Server](https://img.shields.io/badge/Chat-Discord-7289da)](https://discord.gg/dEB6EjQnKB) [![APItoolkit Docs](https://img.shields.io/badge/Read-Docs-0068ff)](https://apitoolkit.io/docs/sdks/dotnet/dotnetcore?utm_source=github-sdks) [![Build Status](https://github.com/apitoolkit/apitoolkit-dotnet/workflows/.NET/badge.svg)](https://github.com/apitoolkit/apitoolkit-dotnet1/actions?query=workflow%3ACI) [![NuGet](https://img.shields.io/nuget/v/ApiToolkit.Net.svg)](https://nuget.org/packages/ApiToolkit.Net) [![Nuget](https://img.shields.io/nuget/dt/ApiToolkit.Net.svg)](https://nuget.org/packages/ApiToolkit.Net) +[![APItoolkit SDK](https://img.shields.io/badge/APItoolkit-SDK-0068ff?logo=dotnet)](https://github.com/topics/apitoolkit-sdk) [![Join Discord Server](https://img.shields.io/badge/Chat-Discord-7289da)](https://apitoolkit.io/discord?utm_campaign=devrel&utm_medium=github&utm_source=apitoolkit_github_profile) [![APItoolkit Docs](https://img.shields.io/badge/Read-Docs-0068ff)](https://apitoolkit.io/docs/sdks/dotnet/dotnetcore?utm_campaign=devrel&utm_medium=github&utm_source=sdks_readme) [![Build Status](https://github.com/apitoolkit/apitoolkit-dotnet/workflows/.NET/badge.svg)](https://github.com/apitoolkit/apitoolkit-dotnet1/actions?query=workflow%3ACI) [![NuGet](https://img.shields.io/nuget/v/ApiToolkit.Net.svg)](https://nuget.org/packages/ApiToolkit.Net) [![Nuget](https://img.shields.io/nuget/dt/ApiToolkit.Net.svg)](https://nuget.org/packages/ApiToolkit.Net) APItoolkit is an end-to-end API and web services management toolkit for engineers and customer support teams. To integrate .Net web services with APItoolkit, you need to use this SDK to monitor incoming traffic, aggregate the requests, and then deliver them to the APItoolkit's servers. @@ -63,19 +63,19 @@ app.Use(async (context, next) => > [!NOTE] > > - Please make sure the APItoolkit middleware is added before `UseEndpoint` and other middleware are initialized. -> - The `{ENTER_YOUR_API_KEY_HERE}` demo string should be replaced with the [API key](https://apitoolkit.io/docs/dashboard/settings-pages/api-keys?utm_source=github-sdks) generated from the APItoolkit dashboard. +> - The `{ENTER_YOUR_API_KEY_HERE}` demo string should be replaced with the [API key](https://apitoolkit.io/docs/dashboard/settings-pages/api-keys?utm_campaign=devrel&utm_medium=github&utm_source=sdks_readme) generated from the APItoolkit dashboard.
> [!IMPORTANT] > -> To learn more configuration options (redacting fields, error reporting, outgoing requests, etc.), please read this [SDK documentation](https://apitoolkit.io/docs/sdks/dotnet/dotnetcore?utm_source=github-sdks). +> To learn more configuration options (redacting fields, error reporting, outgoing requests, etc.), please read this [SDK documentation](https://apitoolkit.io/docs/sdks/dotnet/dotnetcore?utm_campaign=devrel&utm_medium=github&utm_source=sdks_readme). ## Contributing and Help To contribute to the development of this SDK or request help from the community and our team, kindly do any of the following: - Read our [Contributors Guide](https://github.com/apitoolkit/.github/blob/main/CONTRIBUTING.md). -- Join our community [Discord Server](https://discord.gg/dEB6EjQnKB). +- Join our community [Discord Server](https://apitoolkit.io/discord?utm_campaign=devrel&utm_medium=github&utm_source=apitoolkit_github_profile). - Create a [new issue](https://github.com/apitoolkit/apitoolkit-dotnet/issues/new/choose) in this repository. ## License @@ -86,6 +86,6 @@ This repository is published under the [MIT](LICENSE) license.
- +
From f27ba9b793aef0feb743363becc1d3aee6769e4f Mon Sep 17 00:00:00 2001 From: Bolaji Ayodeji Date: Wed, 10 Jul 2024 10:11:01 +0100 Subject: [PATCH 2/4] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 63c8998..118b593 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## .NET Core SDK -[![APItoolkit SDK](https://img.shields.io/badge/APItoolkit-SDK-0068ff?logo=dotnet)](https://github.com/topics/apitoolkit-sdk) [![Join Discord Server](https://img.shields.io/badge/Chat-Discord-7289da)](https://apitoolkit.io/discord?utm_campaign=devrel&utm_medium=github&utm_source=apitoolkit_github_profile) [![APItoolkit Docs](https://img.shields.io/badge/Read-Docs-0068ff)](https://apitoolkit.io/docs/sdks/dotnet/dotnetcore?utm_campaign=devrel&utm_medium=github&utm_source=sdks_readme) [![Build Status](https://github.com/apitoolkit/apitoolkit-dotnet/workflows/.NET/badge.svg)](https://github.com/apitoolkit/apitoolkit-dotnet1/actions?query=workflow%3ACI) [![NuGet](https://img.shields.io/nuget/v/ApiToolkit.Net.svg)](https://nuget.org/packages/ApiToolkit.Net) [![Nuget](https://img.shields.io/nuget/dt/ApiToolkit.Net.svg)](https://nuget.org/packages/ApiToolkit.Net) +[![APItoolkit SDK](https://img.shields.io/badge/APItoolkit-SDK-0068ff?logo=dotnet)](https://github.com/topics/apitoolkit-sdk) [![Join Discord Server](https://img.shields.io/badge/Chat-Discord-7289da)](https://apitoolkit.io/discord?utm_campaign=devrel&utm_medium=github&utm_source=sdks_readme) [![APItoolkit Docs](https://img.shields.io/badge/Read-Docs-0068ff)](https://apitoolkit.io/docs/sdks/dotnet/dotnetcore?utm_campaign=devrel&utm_medium=github&utm_source=sdks_readme) [![Build Status](https://github.com/apitoolkit/apitoolkit-dotnet/workflows/.NET/badge.svg)](https://github.com/apitoolkit/apitoolkit-dotnet1/actions?query=workflow%3ACI) [![NuGet](https://img.shields.io/nuget/v/ApiToolkit.Net.svg)](https://nuget.org/packages/ApiToolkit.Net) [![Nuget](https://img.shields.io/nuget/dt/ApiToolkit.Net.svg)](https://nuget.org/packages/ApiToolkit.Net) APItoolkit is an end-to-end API and web services management toolkit for engineers and customer support teams. To integrate .Net web services with APItoolkit, you need to use this SDK to monitor incoming traffic, aggregate the requests, and then deliver them to the APItoolkit's servers. @@ -75,7 +75,7 @@ app.Use(async (context, next) => To contribute to the development of this SDK or request help from the community and our team, kindly do any of the following: - Read our [Contributors Guide](https://github.com/apitoolkit/.github/blob/main/CONTRIBUTING.md). -- Join our community [Discord Server](https://apitoolkit.io/discord?utm_campaign=devrel&utm_medium=github&utm_source=apitoolkit_github_profile). +- Join our community [Discord Server](https://apitoolkit.io/discord?utm_campaign=devrel&utm_medium=github&utm_source=sdks_readme). - Create a [new issue](https://github.com/apitoolkit/apitoolkit-dotnet/issues/new/choose) in this repository. ## License From 837544b93a0106795b1c845e19022768e9651f22 Mon Sep 17 00:00:00 2001 From: shepherrrd Date: Sat, 10 Aug 2024 13:44:52 +0100 Subject: [PATCH 3/4] feat: Add IApiToolkitClientFactory interface and implementation - Added IApiToolkitClientFactory interface to provide an abstraction for creating HttpClient instances with specific ATOptions. - Implemented ApiToolkitClientFactory class, which leverages HttpClientFactory for centralized management of HttpClient instances. --- ApiToolKit.cs | 32 ++++++++++++++++++++++++- README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/ApiToolKit.cs b/ApiToolKit.cs index 9e6f0cf..cd0c90d 100644 --- a/ApiToolKit.cs +++ b/ApiToolKit.cs @@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System.Diagnostics; +using Microsoft.Extensions.DependencyInjection; using System.Text.Json; using static System.Web.HttpUtility; @@ -424,6 +425,31 @@ public class ATError public string StackTrace { get; set; } } +public interface IApiToolkitClientFactory +{ + HttpClient CreateClient(ATOptions options); +} + +public class ApiToolkitClientFactory : IApiToolkitClientFactory +{ + private readonly IHttpClientFactory _httpClientFactory; + private readonly IServiceProvider _serviceProvider; + + public ApiToolkitClientFactory(IHttpClientFactory httpClientFactory, IServiceProvider serviceProvider) + { + _httpClientFactory = httpClientFactory; + _serviceProvider = serviceProvider; + } + + public HttpClient CreateClient(ATOptions options) + { + var client = _httpClientFactory.CreateClient(); + + var handler = _serviceProvider.GetRequiredService(); + handler.SetOptions(options); + return new HttpClient(handler); + } +} public class ATOptions { @@ -436,9 +462,13 @@ public class ObservingHandler : DelegatingHandler { private readonly HttpContext _context; private readonly Func _publishMessageAsync; - private readonly ATOptions _options; + private ATOptions _options; private readonly string _project_id; private readonly string? _msg_id; + public void SetOptions(ATOptions options) + { + _options = options; + } public ObservingHandler(Func publishMessage, string project_id, HttpContext? httpContext = null, ATOptions? options = null) : base(new HttpClientHandler()) { _context = httpContext ?? throw new ArgumentNullException(nameof(httpContext)); diff --git a/README.md b/README.md index 118b593..c03f7d9 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,11 @@ Next, initialize APItoolkit in your application's entry point (e.g., `Program.cs using ApiToolkit.Net; // Initialize the APItoolkit client +builder.Services.AddTransient(); + +// Register the custom API Toolkit Client Factory +builder.Services.AddSingleton(); + var config = new Config { ApiKey = "{ENTER_YOUR_API_KEY_HERE}", @@ -60,6 +65,66 @@ app.Use(async (context, next) => # ... ``` +## Usage + +You can now use the IApiToolKitClientFactory Interface to directly make your Http requests + +```csharp +public class MyService +{ + private readonly IApiToolkitClientFactory _apiToolkitClientFactory; + + public MyService(IApiToolkitClientFactory apiToolkitClientFactory) + { + _apiToolkitClientFactory = apiToolkitClientFactory; + } + + public async Task GetPostAsync() + { + var options = new ATOptions + { + PathWildCard = "/posts/{id}", + RedactHeaders = new[] { "User-Agent" }, + RedactRequestBody = new[] { "$.user.password" }, + RedactResponseBody = new[] { "$.user.data.email" } + }; + + var client = _apiToolkitClientFactory.CreateClient(options); + var response = await client.GetAsync("https://jsonplaceholder.typicode.com/posts/1"); + return await response.Content.ReadAsStringAsync(); + } +} +``` + +Traditional Middleware Setup +If you prefer to set up the middleware traditionally, here's how you can initialize APItoolkit in your application's entry point (e.g., Program.cs): + +```csharp +using ApiToolkit.Net; + +// Initialize the APItoolkit client +var config = new Config +{ + ApiKey = "{ENTER_YOUR_API_KEY_HERE}", + Debug = false, + Tags = new List { "environment: production", "region: us-east-1" }, + ServiceVersion: "v2.0", +}; +var client = await APIToolkit.NewClientAsync(config); + +// Register the middleware to use the initialized client +app.Use(async (context, next) => +{ + var apiToolkit = new APIToolkit(next, client); + await apiToolkit.InvokeAsync(context); +}); + +// app.UseEndpoint(..) +// other middleware and logic +// ... +``` + + > [!NOTE] > > - Please make sure the APItoolkit middleware is added before `UseEndpoint` and other middleware are initialized. From 99b6c2745a1059c52789426c2aae72053e7c50c3 Mon Sep 17 00:00:00 2001 From: shepherrrd Date: Sat, 10 Aug 2024 13:55:19 +0100 Subject: [PATCH 4/4] feat: Add IApiToolkitClientFactory interface and implementation - Added IApiToolkitClientFactory interface to provide an abstraction for creating HttpClient instances with specific ATOptions. - Implemented ApiToolkitClientFactory class, which leverages HttpClientFactory for centralized management of HttpClient instances. -Added tests For The IApiToolKitCLientFactory --- ApiToolkitTests.cs | 75 +++++++++++++++++++++++++++++++++++++++- apitoolkit-dotnet.csproj | 1 + 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/ApiToolkitTests.cs b/ApiToolkitTests.cs index b5c593e..144dd1f 100644 --- a/ApiToolkitTests.cs +++ b/ApiToolkitTests.cs @@ -10,7 +10,9 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using Microsoft.AspNetCore.Builder; - +using Moq; +using System.Net.Http; +using Microsoft.Extensions.DependencyInjection; public class RedactTests { [Test] @@ -208,3 +210,74 @@ public async Task MiddlewareTest_ReturnsNotFoundForRequest() } } + + public class ApiToolkitClientFactoryTests + { + private Mock _httpClientFactoryMock; + private Mock _serviceProviderMock; + private Mock _observingHandlerMock; + private IApiToolkitClientFactory _apiToolkitClientFactory; + + [SetUp] + public void SetUp() + { + _httpClientFactoryMock = new Mock(); + _serviceProviderMock = new Mock(); + _observingHandlerMock = new Mock(); + + // Set up the service provider to return the observing handler mock + _serviceProviderMock + .Setup(sp => sp.GetService(typeof(ObservingHandler))) + .Returns(_observingHandlerMock.Object); + + // Initialize the ApiToolkitClientFactory with mocks + _apiToolkitClientFactory = new ApiToolkitClientFactory(_httpClientFactoryMock.Object, _serviceProviderMock.Object); + } + + [Test] + public void CreateClient_ShouldReturnHttpClient_WithConfiguredHandler() + { + // Arrange + var options = new ATOptions + { + PathWildCard = "/posts/{id}", + RedactHeaders = new List { "User-Agent" }, + RedactRequestBody = new List { "$.user.password" }, + RedactResponseBody = new List { "$.user.data.email" } + }; + + // Act + var client = _apiToolkitClientFactory.CreateClient(options); + + // Assert + Assert.NotNull(client); + _observingHandlerMock.Verify(h => h.SetOptions(options), Times.Once); + } + + [Test] + public void CreateClient_ShouldUseObservingHandler_FromServiceProvider() + { + // Act + var client = _apiToolkitClientFactory.CreateClient(new ATOptions()); + + // Assert + _serviceProviderMock.Verify(sp => sp.GetService(typeof(ObservingHandler)), Times.Once); + } + + [Test] + public void CreateClient_ShouldThrowException_WhenHandlerNotRegistered() + { + // Arrange + var invalidServiceProvider = new Mock(); + invalidServiceProvider.Setup(sp => sp.GetService(typeof(ObservingHandler))) + .Returns(null); // Simulate missing handler registration + + var factory = new ApiToolkitClientFactory(_httpClientFactoryMock.Object, invalidServiceProvider.Object); + + // Act & Assert + Assert.Throws(() => factory.CreateClient(new ATOptions())); + } + } + + + diff --git a/apitoolkit-dotnet.csproj b/apitoolkit-dotnet.csproj index 573ccf1..6c6e0ae 100644 --- a/apitoolkit-dotnet.csproj +++ b/apitoolkit-dotnet.csproj @@ -28,6 +28,7 @@ +