From 11d2b12de10d66c37276ca3efeef2563503ccc53 Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Thu, 16 Oct 2025 01:10:17 +0330 Subject: [PATCH 01/10] Add "Extensions" folder --- .../FunctionalTest/SuccessScenariosTests.cs | 1 + examples/HttpClientToCurl.Sample.InConsole/ApiCaller.cs | 1 + examples/HttpClientToCurl.Sample.InFile/ApiCaller.cs | 1 + examples/HttpClientToCurl.Sample.InString/ApiCaller.cs | 1 + src/HttpClientToCurl/{ => Extensions}/HttpClientExtensions.cs | 2 +- .../{ => Extensions}/HttpRequestMessageExtensions.cs | 2 +- .../FunctionalTest/SuccessScenariosTests.cs | 2 +- 7 files changed, 7 insertions(+), 3 deletions(-) rename src/HttpClientToCurl/{ => Extensions}/HttpClientExtensions.cs (99%) rename src/HttpClientToCurl/{ => Extensions}/HttpRequestMessageExtensions.cs (98%) diff --git a/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs b/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs index 7a224a5..b381029 100644 --- a/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs +++ b/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs @@ -2,6 +2,7 @@ using System.Text; using FluentAssertions; using HttpClientToCurl; +using HttpClientToCurl.Extensions; using HttpClientToCurl.Utility; using Microsoft.AspNetCore.WebUtilities; diff --git a/examples/HttpClientToCurl.Sample.InConsole/ApiCaller.cs b/examples/HttpClientToCurl.Sample.InConsole/ApiCaller.cs index 9ffcc58..771f648 100644 --- a/examples/HttpClientToCurl.Sample.InConsole/ApiCaller.cs +++ b/examples/HttpClientToCurl.Sample.InConsole/ApiCaller.cs @@ -1,4 +1,5 @@ using System.Text; +using HttpClientToCurl.Extensions; namespace HttpClientToCurl.Sample.InConsole; diff --git a/examples/HttpClientToCurl.Sample.InFile/ApiCaller.cs b/examples/HttpClientToCurl.Sample.InFile/ApiCaller.cs index 4af8f5c..f3cc1ae 100644 --- a/examples/HttpClientToCurl.Sample.InFile/ApiCaller.cs +++ b/examples/HttpClientToCurl.Sample.InFile/ApiCaller.cs @@ -1,4 +1,5 @@ using System.Text; +using HttpClientToCurl.Extensions; namespace HttpClientToCurl.Sample.InFile; diff --git a/examples/HttpClientToCurl.Sample.InString/ApiCaller.cs b/examples/HttpClientToCurl.Sample.InString/ApiCaller.cs index 0f22f94..4974669 100644 --- a/examples/HttpClientToCurl.Sample.InString/ApiCaller.cs +++ b/examples/HttpClientToCurl.Sample.InString/ApiCaller.cs @@ -1,4 +1,5 @@ using System.Text; +using HttpClientToCurl.Extensions; namespace HttpClientToCurl.Sample.InString; diff --git a/src/HttpClientToCurl/HttpClientExtensions.cs b/src/HttpClientToCurl/Extensions/HttpClientExtensions.cs similarity index 99% rename from src/HttpClientToCurl/HttpClientExtensions.cs rename to src/HttpClientToCurl/Extensions/HttpClientExtensions.cs index 499f5da..4b77bbc 100644 --- a/src/HttpClientToCurl/HttpClientExtensions.cs +++ b/src/HttpClientToCurl/Extensions/HttpClientExtensions.cs @@ -3,7 +3,7 @@ using HttpClientToCurl.Config; using HttpClientToCurl.Utility; -namespace HttpClientToCurl; +namespace HttpClientToCurl.Extensions; public static class HttpClientExtensions { diff --git a/src/HttpClientToCurl/HttpRequestMessageExtensions.cs b/src/HttpClientToCurl/Extensions/HttpRequestMessageExtensions.cs similarity index 98% rename from src/HttpClientToCurl/HttpRequestMessageExtensions.cs rename to src/HttpClientToCurl/Extensions/HttpRequestMessageExtensions.cs index 3437dda..a2dcd76 100644 --- a/src/HttpClientToCurl/HttpRequestMessageExtensions.cs +++ b/src/HttpClientToCurl/Extensions/HttpRequestMessageExtensions.cs @@ -2,7 +2,7 @@ using HttpClientToCurl.Config; using HttpClientToCurl.Utility; -namespace HttpClientToCurl; +namespace HttpClientToCurl.Extensions; public static class HttpRequestMessageExtensions { diff --git a/tests/HttpClientToCurlGeneratorTest/FunctionalTest/SuccessScenariosTests.cs b/tests/HttpClientToCurlGeneratorTest/FunctionalTest/SuccessScenariosTests.cs index b8c31d5..6c4faaa 100644 --- a/tests/HttpClientToCurlGeneratorTest/FunctionalTest/SuccessScenariosTests.cs +++ b/tests/HttpClientToCurlGeneratorTest/FunctionalTest/SuccessScenariosTests.cs @@ -1,5 +1,5 @@ using FluentAssertions; -using HttpClientToCurl; +using HttpClientToCurl.Extensions; using HttpClientToCurl.Utility; using Microsoft.AspNetCore.WebUtilities; using System.Net.Http.Headers; From 542083f94018880d6f9dc8d6c248f5d229d4c811 Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Thu, 16 Oct 2025 01:29:44 +0330 Subject: [PATCH 02/10] Add "AddHttpClientToCurl" extension method for global usage --- HttpClientToCurlGenerator.sln | 7 +++ .../Controllers/MyController.cs | 57 +++++++++++++++++++ .../HttpClientToCurl.Sample.InGlobal.csproj | 17 ++++++ .../Program.cs | 29 ++++++++++ .../Properties/launchSettings.json | 23 ++++++++ .../appsettings.Development.json | 8 +++ .../appsettings.json | 9 +++ src/HttpClientToCurl/Config/GlobalConfig.cs | 21 +++++++ .../Extensions/ServiceCollectionExtensions.cs | 26 +++++++++ src/HttpClientToCurl/HttpClientToCurl.csproj | 7 ++- .../CurlGeneratorHttpMessageHandler.cs | 32 +++++++++++ .../HttpMessageHandlerAppender.cs | 17 ++++++ 12 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs create mode 100644 examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj create mode 100644 examples/HttpClientToCurl.Sample.InGlobal/Program.cs create mode 100644 examples/HttpClientToCurl.Sample.InGlobal/Properties/launchSettings.json create mode 100644 examples/HttpClientToCurl.Sample.InGlobal/appsettings.Development.json create mode 100644 examples/HttpClientToCurl.Sample.InGlobal/appsettings.json create mode 100644 src/HttpClientToCurl/Config/GlobalConfig.cs create mode 100644 src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs create mode 100644 src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs create mode 100644 src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs diff --git a/HttpClientToCurlGenerator.sln b/HttpClientToCurlGenerator.sln index 1099594..cbfc7b8 100644 --- a/HttpClientToCurlGenerator.sln +++ b/HttpClientToCurlGenerator.sln @@ -27,6 +27,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solutionItems", "solutionIt EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpRequestMessageToCurlGeneratorTest", "HttpRequestMessageToCurlTest\HttpRequestMessageToCurlGeneratorTest.csproj", "{007CA9E0-CDF0-4375-8E8C-A24C9A7BF531}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpClientToCurl.Sample.InGlobal", "examples\HttpClientToCurl.Sample.InGlobal\HttpClientToCurl.Sample.InGlobal.csproj", "{5A8427BC-0821-E973-7221-263D13156248}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,6 +59,10 @@ Global {007CA9E0-CDF0-4375-8E8C-A24C9A7BF531}.Debug|Any CPU.Build.0 = Debug|Any CPU {007CA9E0-CDF0-4375-8E8C-A24C9A7BF531}.Release|Any CPU.ActiveCfg = Release|Any CPU {007CA9E0-CDF0-4375-8E8C-A24C9A7BF531}.Release|Any CPU.Build.0 = Release|Any CPU + {5A8427BC-0821-E973-7221-263D13156248}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A8427BC-0821-E973-7221-263D13156248}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A8427BC-0821-E973-7221-263D13156248}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A8427BC-0821-E973-7221-263D13156248}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -68,6 +74,7 @@ Global {F7B35144-A00C-45BE-BC41-36C1B21FCD18} = {A8574DB9-8411-4F81-A82E-F97AD00EF8AF} {403B236B-D7D8-43FB-B47E-DCCAF8BA96C4} = {A8574DB9-8411-4F81-A82E-F97AD00EF8AF} {007CA9E0-CDF0-4375-8E8C-A24C9A7BF531} = {E36BF269-7F5D-4DE7-99B0-14567F9CD6B3} + {5A8427BC-0821-E973-7221-263D13156248} = {A8574DB9-8411-4F81-A82E-F97AD00EF8AF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E5E0FFF6-54C3-4BA1-91F3-EF3513A18D5D} diff --git a/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs b/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs new file mode 100644 index 0000000..4bfdd8a --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs @@ -0,0 +1,57 @@ +using System.Text; +using Microsoft.AspNetCore.Mvc; + +namespace HttpClientToCurl.Sample.InGeneral.Controllers; + +[ApiController] +[Route("[controller]")] +public class MyController : ControllerBase +{ + private readonly HttpClient _httpClient; + public MyController(HttpClient httpClient) => _httpClient = httpClient; + + [HttpGet] + public async Task Send() + { + string apiUrl = "https://jsonplaceholder.typicode.com/posts"; + + try + { + // Create a sample JSON payload + string jsonPayload = + "{\"title\":\"New Post\",\"body\":\"This is the body of the new post\",\"userId\":1}"; + + // Create HttpRequestMessage with the POST verb + HttpRequestMessage request = new(HttpMethod.Post, apiUrl); + + // Set up the request headers + request.Headers.Add("Authorization", "Bearer YourAccessToken"); // Add any necessary headers + + // Set the request content with the JSON payload + request.Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + + // Log the curl command for debugging or testing. + // This generates a curl command that can be imported into Postman. + // Use it to check and compare against all the requirements. + + // Send the request + HttpResponseMessage response = await _httpClient.SendAsync(request); + + // Check if the request was successful (status code 200-299) + if (response.IsSuccessStatusCode) + { + // Read and print the response content as a string + string responseBody = await response.Content.ReadAsStringAsync(); + Console.WriteLine("Response from the API:\n" + responseBody); + } + else + { + Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"Exception: {ex.Message}"); + } + } +} diff --git a/examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj b/examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj new file mode 100644 index 0000000..d34b903 --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj @@ -0,0 +1,17 @@ + + + + net9.0 + enable + enable + + + + + + + + + + + diff --git a/examples/HttpClientToCurl.Sample.InGlobal/Program.cs b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs new file mode 100644 index 0000000..db32780 --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs @@ -0,0 +1,29 @@ +using static HttpClientToCurl.Extensions.ServiceCollectionExtensions; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddControllers(); +builder.Services.AddOpenApi(); +builder.Services.AddHttpClientToCurl(config => +{ + config.TurnOnAll = true; + config.ShowOnConsole = consoleConfig => + { + consoleConfig.TurnOn = true; + consoleConfig.EnableCodeBeautification = true; + }; + config.SaveToFile = fileConfig => + { + fileConfig.TurnOn = true; + fileConfig.Filename = "curl_commands.txt"; + fileConfig.Path = "C:\\logs"; + fileConfig.NeedAddDefaultHeaders = true; + }; +}); +builder.Services.AddHttpClient(); + +var app = builder.Build(); + +app.UseHttpsRedirection(); +app.UseAuthorization(); +app.MapControllers(); +app.Run(); diff --git a/examples/HttpClientToCurl.Sample.InGlobal/Properties/launchSettings.json b/examples/HttpClientToCurl.Sample.InGlobal/Properties/launchSettings.json new file mode 100644 index 0000000..2dbac44 --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InGlobal/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5272", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7038;http://localhost:5272", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/examples/HttpClientToCurl.Sample.InGlobal/appsettings.Development.json b/examples/HttpClientToCurl.Sample.InGlobal/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InGlobal/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/examples/HttpClientToCurl.Sample.InGlobal/appsettings.json b/examples/HttpClientToCurl.Sample.InGlobal/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InGlobal/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/src/HttpClientToCurl/Config/GlobalConfig.cs b/src/HttpClientToCurl/Config/GlobalConfig.cs new file mode 100644 index 0000000..f36a0ca --- /dev/null +++ b/src/HttpClientToCurl/Config/GlobalConfig.cs @@ -0,0 +1,21 @@ +namespace HttpClientToCurl.Config; + +public sealed class GlobalConfig +{ + /// + /// Set true to create curl output; false to disable it. Default is true. + /// + public bool TurnOnAll { get; set; } = true; + + /// + /// Set true to show curl on the console; false to disable it. Default is true. + /// If TurnOnAll is set to false, it will be ignored. + /// + public Action ShowOnConsole { get; set; } + + /// + /// Set true to save the curl file; false to disable it. Default is true. + /// If TurnOnAll is set to false, it will be ignored. + /// + public Action SaveToFile { get; set; } +} diff --git a/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs b/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..e10721f --- /dev/null +++ b/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,26 @@ +using HttpClientToCurl.Config; +using HttpClientToCurl.HttpMessageHandlers; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Http; + +namespace HttpClientToCurl.Extensions; + +public static class ServiceCollectionExtensions +{ + /// + /// Generating curl script of all HTTP requests. + /// By default, show it in the IDE console. + /// + /// Optional + public static void AddHttpClientToCurl( + this IServiceCollection services, + Action configAction = null) + { + var config = new GlobalConfig(); + configAction?.Invoke(config); + + services.AddSingleton(config); + services.AddTransient(); + services.Add(ServiceDescriptor.Transient()); + } +} diff --git a/src/HttpClientToCurl/HttpClientToCurl.csproj b/src/HttpClientToCurl/HttpClientToCurl.csproj index b999219..7a7438c 100644 --- a/src/HttpClientToCurl/HttpClientToCurl.csproj +++ b/src/HttpClientToCurl/HttpClientToCurl.csproj @@ -1,4 +1,4 @@ - + Amin Golmahalleh @@ -22,4 +22,9 @@ + + + + + diff --git a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs new file mode 100644 index 0000000..10a86bd --- /dev/null +++ b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs @@ -0,0 +1,32 @@ +using HttpClientToCurl.Config; +using HttpClientToCurl.Extensions; + +namespace HttpClientToCurl.HttpMessageHandlers; + +public class CurlGeneratorHttpMessageHandler : DelegatingHandler +{ + private readonly GlobalConfig _config; + + public CurlGeneratorHttpMessageHandler(GlobalConfig config) => _config = config; + + protected override Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + { + if (_config.TurnOnAll) + { + var consoleConfig = new ConsoleConfig(); + _config.ShowOnConsole?.Invoke(consoleConfig); + if (consoleConfig.TurnOn) + HttpRequestMessageExtensions.GenerateCurlInConsole(request, null); + + var fileConfig = new FileConfig(); + _config.SaveToFile?.Invoke(fileConfig); + if (fileConfig.TurnOn) + HttpRequestMessageExtensions.GenerateCurlInFile(request, null, _config.SaveToFile); + } + + var response = base.SendAsync(request, cancellationToken); + return response; + } +} diff --git a/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs b/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs new file mode 100644 index 0000000..7c5293a --- /dev/null +++ b/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Http; + +namespace HttpClientToCurl.HttpMessageHandlers; +public class HttpMessageHandlerAppender : IHttpMessageHandlerBuilderFilter +{ + private readonly IServiceProvider _serviceProvider; + + public HttpMessageHandlerAppender(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; + + public Action Configure(Action next) => builder => + { + next(builder); + var handler = _serviceProvider.GetRequiredService(); + builder.AdditionalHandlers.Add(handler); + }; +} From 76e3aa6a995c7e7d8b6db726bff0768a53d36366 Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Thu, 16 Oct 2025 09:34:07 +0330 Subject: [PATCH 03/10] Downgrade .net version to fix ci/cd pipeline error --- .../HttpClientToCurl.Sample.InGlobal.csproj | 7 ++----- examples/HttpClientToCurl.Sample.InGlobal/Program.cs | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj b/examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj index d34b903..c6c2b8b 100644 --- a/examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj +++ b/examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj @@ -1,15 +1,12 @@ - net9.0 + net8.0 enable enable + - - - - diff --git a/examples/HttpClientToCurl.Sample.InGlobal/Program.cs b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs index db32780..e75c22e 100644 --- a/examples/HttpClientToCurl.Sample.InGlobal/Program.cs +++ b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs @@ -2,7 +2,6 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); -builder.Services.AddOpenApi(); builder.Services.AddHttpClientToCurl(config => { config.TurnOnAll = true; From 4d725e82231153ff1bc2237287e3ce47b91e0fee Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Thu, 16 Oct 2025 09:48:36 +0330 Subject: [PATCH 04/10] Apply restricted code style to run the CI/CD pipeline properly --- .../FunctionalTest/SuccessScenariosTests.cs | 1 - .../Controllers/MyController.cs | 9 ++++----- .../CurlGeneratorHttpMessageHandler.cs | 18 +++++++++--------- .../HttpMessageHandlerAppender.cs | 8 ++------ src/HttpClientToCurl/Utility/Helpers.cs | 2 +- 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs b/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs index b381029..8c39748 100644 --- a/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs +++ b/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs @@ -1,7 +1,6 @@ using System.Net.Mime; using System.Text; using FluentAssertions; -using HttpClientToCurl; using HttpClientToCurl.Extensions; using HttpClientToCurl.Utility; using Microsoft.AspNetCore.WebUtilities; diff --git a/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs b/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs index 4bfdd8a..25600a8 100644 --- a/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs +++ b/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs @@ -1,14 +1,13 @@ using System.Text; using Microsoft.AspNetCore.Mvc; -namespace HttpClientToCurl.Sample.InGeneral.Controllers; +namespace HttpClientToCurl.Sample.InGlobal.Controllers; [ApiController] [Route("[controller]")] -public class MyController : ControllerBase +public class MyController(HttpClient httpClient) : ControllerBase { - private readonly HttpClient _httpClient; - public MyController(HttpClient httpClient) => _httpClient = httpClient; + private readonly HttpClient _httpClient = httpClient; [HttpGet] public async Task Send() @@ -19,7 +18,7 @@ public async Task Send() { // Create a sample JSON payload string jsonPayload = - "{\"title\":\"New Post\",\"body\":\"This is the body of the new post\",\"userId\":1}"; + $"{{\"title\":\"New Post\",\"body\":\"This is the body of the new post\",\"userId\":1}}"; // Create HttpRequestMessage with the POST verb HttpRequestMessage request = new(HttpMethod.Post, apiUrl); diff --git a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs index 10a86bd..e77b2f9 100644 --- a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs +++ b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs @@ -3,27 +3,27 @@ namespace HttpClientToCurl.HttpMessageHandlers; -public class CurlGeneratorHttpMessageHandler : DelegatingHandler +public class CurlGeneratorHttpMessageHandler(GlobalConfig config) : DelegatingHandler { - private readonly GlobalConfig _config; - - public CurlGeneratorHttpMessageHandler(GlobalConfig config) => _config = config; - protected override Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { - if (_config.TurnOnAll) + if (config.TurnOnAll) { var consoleConfig = new ConsoleConfig(); - _config.ShowOnConsole?.Invoke(consoleConfig); + config.ShowOnConsole?.Invoke(consoleConfig); if (consoleConfig.TurnOn) + { HttpRequestMessageExtensions.GenerateCurlInConsole(request, null); + } var fileConfig = new FileConfig(); - _config.SaveToFile?.Invoke(fileConfig); + config.SaveToFile?.Invoke(fileConfig); if (fileConfig.TurnOn) - HttpRequestMessageExtensions.GenerateCurlInFile(request, null, _config.SaveToFile); + { + HttpRequestMessageExtensions.GenerateCurlInFile(request, null, config.SaveToFile); + } } var response = base.SendAsync(request, cancellationToken); diff --git a/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs b/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs index 7c5293a..fa35ae5 100644 --- a/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs +++ b/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs @@ -2,16 +2,12 @@ using Microsoft.Extensions.Http; namespace HttpClientToCurl.HttpMessageHandlers; -public class HttpMessageHandlerAppender : IHttpMessageHandlerBuilderFilter +public class HttpMessageHandlerAppender(IServiceProvider serviceProvider) : IHttpMessageHandlerBuilderFilter { - private readonly IServiceProvider _serviceProvider; - - public HttpMessageHandlerAppender(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; - public Action Configure(Action next) => builder => { next(builder); - var handler = _serviceProvider.GetRequiredService(); + var handler = serviceProvider.GetRequiredService(); builder.AdditionalHandlers.Add(handler); }; } diff --git a/src/HttpClientToCurl/Utility/Helpers.cs b/src/HttpClientToCurl/Utility/Helpers.cs index 3a8876a..2ff347b 100644 --- a/src/HttpClientToCurl/Utility/Helpers.cs +++ b/src/HttpClientToCurl/Utility/Helpers.cs @@ -78,7 +78,7 @@ private static string NormalizedPath(string path) if (inputPath.EndsWith('/')) { - inputPath = inputPath.Remove(inputPath.Length - 1); + inputPath = inputPath[..^1]; } return inputPath; From f3b10ecd6c540e07215bb24d61acf3f71bb8ac87 Mon Sep 17 00:00:00 2001 From: Hamed Naeemaei Date: Sun, 19 Oct 2025 17:06:52 +0330 Subject: [PATCH 05/10] Resolve conflicts --- .../FunctionalTest/SuccessScenariosTests.cs | 261 ------------- ...tpRequestMessageToCurlGeneratorTest.csproj | 32 -- .../Json/FailedCurlGeneratorTests.cs | 30 -- .../Json/SuccessCurlGeneratorTests.cs | 353 ------------------ .../Xml/SuccessCurlGeneratorTests.cs | 84 ----- 5 files changed, 760 deletions(-) delete mode 100644 HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs delete mode 100644 HttpRequestMessageToCurlTest/HttpRequestMessageToCurlGeneratorTest.csproj delete mode 100644 HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Json/FailedCurlGeneratorTests.cs delete mode 100644 HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Json/SuccessCurlGeneratorTests.cs delete mode 100644 HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Xml/SuccessCurlGeneratorTests.cs diff --git a/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs b/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs deleted file mode 100644 index 8c39748..0000000 --- a/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs +++ /dev/null @@ -1,261 +0,0 @@ -using System.Net.Mime; -using System.Text; -using FluentAssertions; -using HttpClientToCurl.Extensions; -using HttpClientToCurl.Utility; -using Microsoft.AspNetCore.WebUtilities; - -namespace HttpRequestMessageToCurlGeneratorTest.FunctionalTest; - -public class SuccessScenariosTests -{ - #region :: GenerateCurlInString For Post Method :: - - [Fact] - public void Success_GenerateCurlInString_For_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""sara"",""requestId"":10001001,""amount"":20000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - var baseAddress = new Uri("http://localhost:1213/v1/"); - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl -X POST"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""sara"",""requestId"":10001001,""amount"":20000}'"); - } - - [Fact] - public void Success_GenerateCurlInString_With_RequestUri_TypeOf_Uri_For_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""sara"",""requestId"":10001001,""amount"":20000}"; - - var requestUri = Helpers.CreateUri("api/test"); - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl -X POST"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""sara"",""requestId"":10001001,""amount"":20000}'"); - } - - [Fact] - public void GenerateCurl_When_Set_RequestUri_Inside_HttpRequestMessage_For_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""sara"",""requestId"":10001001,""amount"":20000}"; - - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, "api/test") { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - using var httpClient = new HttpClient(); - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl -X POST"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""sara"",""requestId"":10001001,""amount"":20000}'"); - } - - [Fact] - public void Success_GenerateCurlInString_When_RequestUri_Is_Null_For_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""sara"",""requestId"":10001001,""amount"":20000}"; - - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, string.Empty) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl -X POST"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""sara"",""requestId"":10001001,""amount"":20000}'"); - } - - [Fact] - public void Success_GenerateCurlInString_When_RequestBody_Is_Null_For_PostMethod() - { - // Arrange - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl -X POST"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d ''"); - } - - [Fact] - public void Success_GenerateCurlInString_When_HttpContent_Is_Null_For_PostMethod() - { - // Arrange - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri); - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - using var httpClient = new HttpClient(); - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl -X POST"); - curlResult.Trim().Should().BeEquivalentTo(@"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -d ''"); - } - - [Fact] - public void Success_GenerateCurlInString_With_Multiple_Value_For_A_Header_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""sara"",""requestId"":10001001,""amount"":20000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - List headerValues = ["_ga=GA1.1.41226618.1701506283", "mywebsite-sp=cbf42587-7ec5-4179-aac5-cbc9ae6fbf05", "sp_ses.13cb=*"]; - httpRequestMessage.Headers.Add("cookie", headerValues); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl -X POST"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Cookie: _ga=GA1.1.41226618.1701506283; mywebsite-sp=cbf42587-7ec5-4179-aac5-cbc9ae6fbf05; sp_ses.13cb=*' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""sara"",""requestId"":10001001,""amount"":20000}'"); - } - - #endregion - - #region :: GenerateCurlInString For Get Method :: - - [Fact] - public void Success_GenerateCurlInString_For_GetMethod() - { - // Arrange - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri) { Content = new StringContent(string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9' -H 'Content-Type: application/json; charset=utf-8'"); - } - - [Fact] - public void Success_GenerateCurlInString_With_QueryString_For_GetMethod() - { - // Arrange - var queryString = new Dictionary { { "id", "12" } }; - var requestUri = QueryHelpers.AddQueryString("api/test", queryString!); - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri) { Content = new StringContent(string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl 'http://localhost:1213/v1/api/test?id=12' -H 'Authorization: Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9' -H 'Content-Type: application/json; charset=utf-8'"); - } - - [Fact] - public void Success_GenerateCurlInString_When_RequestUri_Is_Null_For_GetMethod() - { - // Arrange - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, string.Empty) { Content = new StringContent(string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl"); - curlResult.Trim().Should() - .BeEquivalentTo(@"curl 'http://localhost:1213/v1/' -H 'Authorization: Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9' -H 'Content-Type: application/json; charset=utf-8'"); - } - - [Fact] - public void Success_GenerateCurlInString_With_Multiple_Value_For_A_Header_GetMethod() - { - // Arrange - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri) { Content = new StringContent(string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9"); - - List headerValues = ["_ga=GA1.1.41226618.1701506283", "mywebsite-sp=cbf42587-7ec5-4179-aac5-cbc9ae6fbf05", "sp_ses.13cb=*"]; - httpRequestMessage.Headers.Add("cookie", headerValues); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string curlResult = httpRequestMessage.GenerateCurlInString(baseAddress); - - // Assert - curlResult.Should().NotBeNullOrEmpty(); - curlResult.Should().StartWith("curl"); - curlResult.Trim().Should() - .BeEquivalentTo( - @"curl 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9' -H 'Cookie: _ga=GA1.1.41226618.1701506283; mywebsite-sp=cbf42587-7ec5-4179-aac5-cbc9ae6fbf05; sp_ses.13cb=*' -H 'Content-Type: application/json; charset=utf-8'"); - } - - #endregion -} diff --git a/HttpRequestMessageToCurlTest/HttpRequestMessageToCurlGeneratorTest.csproj b/HttpRequestMessageToCurlTest/HttpRequestMessageToCurlGeneratorTest.csproj deleted file mode 100644 index 935078a..0000000 --- a/HttpRequestMessageToCurlTest/HttpRequestMessageToCurlGeneratorTest.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net8.0 - enable - enable - - false - true - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - diff --git a/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Json/FailedCurlGeneratorTests.cs b/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Json/FailedCurlGeneratorTests.cs deleted file mode 100644 index d377e03..0000000 --- a/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Json/FailedCurlGeneratorTests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Net.Mime; -using System.Text; -using HttpClientToCurl.Builder; - -namespace HttpRequestMessageToCurlGeneratorTest.UnitTest.MediaTypes.Json; - -public class FailedCurlGeneratorTests -{ - [Fact] - public void GenerateCurl_When_HttpMethod_Is_Invalid() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""russel"",""requestId"":10001004,""amount"":50000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Trace, requestUri) - { - Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) - }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - Assert - Assert.Throws(() => Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null)); - } -} diff --git a/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Json/SuccessCurlGeneratorTests.cs b/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Json/SuccessCurlGeneratorTests.cs deleted file mode 100644 index 52a7576..0000000 --- a/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Json/SuccessCurlGeneratorTests.cs +++ /dev/null @@ -1,353 +0,0 @@ -using System.Net.Mime; -using System.Text; -using FluentAssertions; -using HttpClientToCurl.Builder; -using Microsoft.AspNetCore.WebUtilities; - -namespace HttpRequestMessageToCurlGeneratorTest.UnitTest.MediaTypes.Json; - -public class SuccessCurlGeneratorTests -{ - [Fact] - public void GenerateCurl_For_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""sara"",""requestId"":10001001,""amount"":20000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""sara"",""requestId"":10001001,""amount"":20000}'"); - } - - [Fact] - public void GenerateCurl_With_ContentLength_For_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""sara"",""requestId"":10001001,""amount"":20000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer f69406a4-6b62-4734-a8dc-158f0fc308ab"); - httpRequestMessage.Content.Headers.Add("Content-Length", "123"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer f69406a4-6b62-4734-a8dc-158f0fc308ab' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""sara"",""requestId"":10001001,""amount"":20000}'"); - } - - [Fact] - public void GenerateCurl_With_QueryString_For_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""amin"",""requestId"":10001000,""amount"":10000}"; - - var queryString = new Dictionary { { "id", "12" }, { "name", "Morten Sjøgren" }, { "nationalCode", "123-456-7890" } }; - var requestUri = QueryHelpers.AddQueryString("api/test", queryString!); - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test?id=12&name=Morten%20Sj%C3%B8gren&nationalCode=123-456-7890' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""amin"",""requestId"":10001000,""amount"":10000}'"); - } - - [Fact] - public void GenerateCurl_UrlEncoded_For_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""justin"",""requestId"":10001026,""amount"":26000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) - { - Content = new FormUrlEncodedContent(new[] - { - new KeyValuePair("session", "703438f3-16ad-4ba5-b923-8f72cd0f2db9"), new KeyValuePair("payload", requestBody), - }) - }; - - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/x-www-form-urlencoded' -d 'session=703438f3-16ad-4ba5-b923-8f72cd0f2db9' -d 'payload={""name"":""justin"",""requestId"":10001026,""amount"":26000}'"); - } - - [Fact] - public void GenerateCurl_Without_RequestBody_For_PostMethod() - { - // Arrange - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(string.Empty, Encoding.UTF8, "application/json") }; - httpRequestMessage.Headers.Add("Authorization", "Bearer c332e9a1-1e0e-44c2-b819-b0e7e8ff7d45"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer c332e9a1-1e0e-44c2-b819-b0e7e8ff7d45' -H 'Content-Type: application/json; charset=utf-8' -d ''"); - } - - [Fact] - public void GenerateCurl_Without_Content_For_PostMethod() - { - // Arrange - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = null }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 56bfa7a0-0541-4d71-9efc-8b28219ac31a"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 56bfa7a0-0541-4d71-9efc-8b28219ac31a' -d ''"); - } - - [Fact] - public void GenerateCurl_When_Invalid_JsonBody_PostMethod() - { - // Arrange - string requestBody = @"""name"":""steven"",""requestId"":10001005,""amount"":60000"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '""name"":""steven"",""requestId"":10001005,""amount"":60000'"); - } - - [Fact] - public void GenerateCurl_When_BaseAddress_Is_Null_PostMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""nancy"",""requestId"":10001006,""amount"":70000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - Uri? baseAddress = null; - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X POST 'api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""nancy"",""requestId"":10001006,""amount"":70000}'"); - } - - [Fact] - public void GenerateCurl_For_GetMethod() - { - // Arrange - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri) { Content = new StringContent(string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl"); - script.Trim().Should() - .BeEquivalentTo( - @"curl 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9' -H 'Content-Type: application/json; charset=utf-8'"); - } - - [Fact] - public void GenerateCurl_With_QueryString_For_GetMethod() - { - // Arrange - var queryString = new Dictionary { { "id", "12" } }; - var requestUri = QueryHelpers.AddQueryString("api/test", queryString!); - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri) { Content = new StringContent(string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl"); - script.Trim().Should() - .BeEquivalentTo( - @"curl 'http://localhost:1213/v1/api/test?id=12' -H 'Authorization: Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9' -H 'Content-Type: application/json; charset=utf-8'"); - } - - [Fact] - public void GenerateCurl_For_PutMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""reza"",""requestId"":10001002,""amount"":30000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Put, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X PUT"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X PUT 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""reza"",""requestId"":10001002,""amount"":30000}'"); - } - - [Fact] - public void GenerateCurl_For_PatchMethod() - { - // Arrange - string requestBody = /*lang=json,strict*/ @"{""name"":""hamed"",""requestId"":10001003,""amount"":40000}"; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Patch, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Application.Json) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X PATCH"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X PATCH 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: application/json; charset=utf-8' -d '{""name"":""hamed"",""requestId"":10001003,""amount"":40000}'"); - } - - [Fact] - public void GenerateCurl_For_DeleteMethod() - { - // Arrange - var id = 12; - var requestUri = $"api/test/{id}"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Delete, requestUri) - { - Content = new StringContent(string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json) - }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X DELETE"); - script.Trim().Should() - .BeEquivalentTo( - @"curl -X DELETE 'http://localhost:1213/v1/api/test/12' -H 'Authorization: Bearer 703438f3-16ad-4ba5-b923-8f72cd0f2db9' -H 'Content-Type: application/json; charset=utf-8'"); - } -} diff --git a/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Xml/SuccessCurlGeneratorTests.cs b/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Xml/SuccessCurlGeneratorTests.cs deleted file mode 100644 index 1192a76..0000000 --- a/HttpRequestMessageToCurlTest/UnitTest/MediaTypes/Xml/SuccessCurlGeneratorTests.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Net.Mime; -using System.Text; -using FluentAssertions; -using HttpClientToCurl.Builder; - -namespace HttpRequestMessageToCurlGeneratorTest.UnitTest.MediaTypes.Xml; - -public class SuccessCurlGeneratorTests -{ - [Fact] - public void Get_Curl_Script_For_PostMethod() - { - // Arrange - string requestBody = @" - - 12 - Jason - 10001024 - 240000 - "; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Text.Xml) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNullOrEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should().BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: text/xml; charset=utf-8' -d ' - - 12 - Jason - 10001024 - 240000 - '"); - } - - [Fact] - public void Get_Error_Message_When_Input_XML_Is_Invalid_For_PostMethod() - { - // Arrange - string requestBody = @" - - 12 - Jason - 10001024 - 240000 - "; - - var requestUri = "api/test"; - var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = new StringContent(requestBody, Encoding.UTF8, MediaTypeNames.Text.Xml) }; - httpRequestMessage.Headers.Add("Authorization", "Bearer 4797c126-3f8a-454a-aff1-96c0220dae61"); - - var baseAddress = new Uri("http://localhost:1213/v1/"); - - // Act - string script = Generator.GenerateCurl( - httpRequestMessage, - baseAddress, - null); - - // Assert - script.Should().NotBeNull(); - script.Should().NotBeEmpty(); - script.Should().StartWith("curl -X POST"); - script.Trim().Should().BeEquivalentTo( - @"curl -X POST 'http://localhost:1213/v1/api/test' -H 'Authorization: Bearer 4797c126-3f8a-454a-aff1-96c0220dae61' -H 'Content-Type: text/xml; charset=utf-8' -d ' - - 12 - Jason - 10001024 - 240000 - '"); - } -} From 41c024c464fdb87c009a0504b695645ed8071c2c Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Sat, 25 Oct 2025 20:57:59 +0330 Subject: [PATCH 06/10] Simplify "AddHttpClientToCurl" configuration --- .../Program.cs | 19 +++------- src/HttpClientToCurl/Config/GlobalConfig.cs | 38 +++++++++++-------- .../Config/Others/ShowMode.cs | 9 +++++ .../Extensions/ServiceCollectionExtensions.cs | 15 ++++++-- .../CurlGeneratorHttpMessageHandler.cs | 32 +++++++++------- 5 files changed, 68 insertions(+), 45 deletions(-) create mode 100644 src/HttpClientToCurl/Config/Others/ShowMode.cs diff --git a/examples/HttpClientToCurl.Sample.InGlobal/Program.cs b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs index e75c22e..820b7c6 100644 --- a/examples/HttpClientToCurl.Sample.InGlobal/Program.cs +++ b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs @@ -1,22 +1,15 @@ +using HttpClientToCurl.Config.Others; using static HttpClientToCurl.Extensions.ServiceCollectionExtensions; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddHttpClientToCurl(config => { - config.TurnOnAll = true; - config.ShowOnConsole = consoleConfig => - { - consoleConfig.TurnOn = true; - consoleConfig.EnableCodeBeautification = true; - }; - config.SaveToFile = fileConfig => - { - fileConfig.TurnOn = true; - fileConfig.Filename = "curl_commands.txt"; - fileConfig.Path = "C:\\logs"; - fileConfig.NeedAddDefaultHeaders = true; - }; + config.ShowMode = ShowMode.Console | ShowMode.File; + config.NeedAddDefaultHeaders = true; + config.ConsoleEnableCodeBeautification = true; + config.FileConfigPath = "C:\\Users\\Public"; + config.FileConfigFileName = "curl_commands"; }); builder.Services.AddHttpClient(); diff --git a/src/HttpClientToCurl/Config/GlobalConfig.cs b/src/HttpClientToCurl/Config/GlobalConfig.cs index f36a0ca..8378063 100644 --- a/src/HttpClientToCurl/Config/GlobalConfig.cs +++ b/src/HttpClientToCurl/Config/GlobalConfig.cs @@ -1,21 +1,27 @@ -namespace HttpClientToCurl.Config; +using HttpClientToCurl.Config.Others; + +namespace HttpClientToCurl.Config; public sealed class GlobalConfig { - /// - /// Set true to create curl output; false to disable it. Default is true. - /// - public bool TurnOnAll { get; set; } = true; - - /// - /// Set true to show curl on the console; false to disable it. Default is true. - /// If TurnOnAll is set to false, it will be ignored. - /// - public Action ShowOnConsole { get; set; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0032:Use auto property", Justification = "")] + private ShowMode _showMode; - /// - /// Set true to save the curl file; false to disable it. Default is true. - /// If TurnOnAll is set to false, it will be ignored. - /// - public Action SaveToFile { get; set; } + public ShowMode ShowMode + { + get => _showMode; + set + { + if (value is not ShowMode.None && value.HasFlag(ShowMode.None)) + { + throw new ArgumentException("ShowMode.None cannot be combined with other flags."); + } + _showMode = value; + } + } + public bool NeedAddDefaultHeaders { get; set; } = true; + public bool ConsoleEnableCodeBeautification { get; set; } = false; + public bool ConsoleEnableCompression { get; set; } = false; + public string FileConfigFileName { get; set; } + public string FileConfigPath { get; set; } } diff --git a/src/HttpClientToCurl/Config/Others/ShowMode.cs b/src/HttpClientToCurl/Config/Others/ShowMode.cs new file mode 100644 index 0000000..5819520 --- /dev/null +++ b/src/HttpClientToCurl/Config/Others/ShowMode.cs @@ -0,0 +1,9 @@ +namespace HttpClientToCurl.Config.Others; + +[Flags] +public enum ShowMode +{ + None = 1, + Console = 2, + File = 4 +} diff --git a/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs b/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs index e10721f..ce64332 100644 --- a/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs +++ b/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using HttpClientToCurl.Config; +using HttpClientToCurl.Config.Others; using HttpClientToCurl.HttpMessageHandlers; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Http; @@ -12,15 +13,23 @@ public static class ServiceCollectionExtensions /// By default, show it in the IDE console. /// /// Optional + /// Apply for all http requests in the application or not. Default is true. public static void AddHttpClientToCurl( - this IServiceCollection services, - Action configAction = null) + this IServiceCollection services, + Action configAction = null, + bool isGlobal = true) { + configAction ??= config => config.ShowMode = ShowMode.Console; + var config = new GlobalConfig(); configAction?.Invoke(config); services.AddSingleton(config); services.AddTransient(); - services.Add(ServiceDescriptor.Transient()); + + if (isGlobal) + { + services.Add(ServiceDescriptor.Transient()); + } } } diff --git a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs index e77b2f9..4e8c859 100644 --- a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs +++ b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs @@ -1,4 +1,5 @@ using HttpClientToCurl.Config; +using HttpClientToCurl.Config.Others; using HttpClientToCurl.Extensions; namespace HttpClientToCurl.HttpMessageHandlers; @@ -6,27 +7,32 @@ namespace HttpClientToCurl.HttpMessageHandlers; public class CurlGeneratorHttpMessageHandler(GlobalConfig config) : DelegatingHandler { protected override Task SendAsync( - HttpRequestMessage request, + HttpRequestMessage httpRequestMessage, CancellationToken cancellationToken) { - if (config.TurnOnAll) + if (config.ShowMode.HasFlag(ShowMode.Console)) { - var consoleConfig = new ConsoleConfig(); - config.ShowOnConsole?.Invoke(consoleConfig); - if (consoleConfig.TurnOn) + httpRequestMessage.GenerateCurlInConsole(httpRequestMessage.RequestUri, consoleConfig => { - HttpRequestMessageExtensions.GenerateCurlInConsole(request, null); - } + consoleConfig.TurnOn = true; + consoleConfig.EnableCodeBeautification = config.ConsoleEnableCodeBeautification; + consoleConfig.EnableCompression = config.ConsoleEnableCompression; + consoleConfig.NeedAddDefaultHeaders = config.NeedAddDefaultHeaders; + }); + } - var fileConfig = new FileConfig(); - config.SaveToFile?.Invoke(fileConfig); - if (fileConfig.TurnOn) + if (config.ShowMode.HasFlag(ShowMode.File)) + { + httpRequestMessage.GenerateCurlInFile(httpRequestMessage.RequestUri, fileConfig => { - HttpRequestMessageExtensions.GenerateCurlInFile(request, null, config.SaveToFile); - } + fileConfig.TurnOn = true; + fileConfig.Filename = config.FileConfigFileName; + fileConfig.Path = config.FileConfigPath; + fileConfig.NeedAddDefaultHeaders = config.NeedAddDefaultHeaders; + }); } - var response = base.SendAsync(request, cancellationToken); + var response = base.SendAsync(httpRequestMessage, cancellationToken); return response; } } From 57394ecf88a7719ab990adc1041c85500dd55eb5 Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Sat, 25 Oct 2025 20:58:58 +0330 Subject: [PATCH 07/10] Add Sample.InSpecific project --- HttpClientToCurlGenerator.sln | 7 +++ .../Controllers/MyController.cs | 56 +++++++++++++++++++ .../HttpClientToCurl.Sample.InSpecific.csproj | 13 +++++ .../Program.cs | 23 ++++++++ .../Properties/launchSettings.json | 23 ++++++++ .../appsettings.Development.json | 8 +++ .../appsettings.json | 9 +++ 7 files changed, 139 insertions(+) create mode 100644 examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs create mode 100644 examples/HttpClientToCurl.Sample.InSpecific/HttpClientToCurl.Sample.InSpecific.csproj create mode 100644 examples/HttpClientToCurl.Sample.InSpecific/Program.cs create mode 100644 examples/HttpClientToCurl.Sample.InSpecific/Properties/launchSettings.json create mode 100644 examples/HttpClientToCurl.Sample.InSpecific/appsettings.Development.json create mode 100644 examples/HttpClientToCurl.Sample.InSpecific/appsettings.json diff --git a/HttpClientToCurlGenerator.sln b/HttpClientToCurlGenerator.sln index d42a6e9..34648e8 100644 --- a/HttpClientToCurlGenerator.sln +++ b/HttpClientToCurlGenerator.sln @@ -29,6 +29,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpClientToCurlTest", "tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpRequestMessageToCurlTest", "tests\HttpRequestMessageToCurlTest\HttpRequestMessageToCurlTest.csproj", "{69E31075-F14E-1DE2-1D6E-D934A5C0480F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpClientToCurl.Sample.InSpecific", "examples\HttpClientToCurl.Sample.InSpecific\HttpClientToCurl.Sample.InSpecific.csproj", "{9D56718F-C9E6-4C45-926D-97599072DA35}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +65,10 @@ Global {69E31075-F14E-1DE2-1D6E-D934A5C0480F}.Debug|Any CPU.Build.0 = Debug|Any CPU {69E31075-F14E-1DE2-1D6E-D934A5C0480F}.Release|Any CPU.ActiveCfg = Release|Any CPU {69E31075-F14E-1DE2-1D6E-D934A5C0480F}.Release|Any CPU.Build.0 = Release|Any CPU + {9D56718F-C9E6-4C45-926D-97599072DA35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D56718F-C9E6-4C45-926D-97599072DA35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D56718F-C9E6-4C45-926D-97599072DA35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D56718F-C9E6-4C45-926D-97599072DA35}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -75,6 +81,7 @@ Global {5A8427BC-0821-E973-7221-263D13156248} = {A8574DB9-8411-4F81-A82E-F97AD00EF8AF} {8CC76F1F-5845-D81E-5E9A-113F913A444B} = {E36BF269-7F5D-4DE7-99B0-14567F9CD6B3} {69E31075-F14E-1DE2-1D6E-D934A5C0480F} = {E36BF269-7F5D-4DE7-99B0-14567F9CD6B3} + {9D56718F-C9E6-4C45-926D-97599072DA35} = {A8574DB9-8411-4F81-A82E-F97AD00EF8AF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E5E0FFF6-54C3-4BA1-91F3-EF3513A18D5D} diff --git a/examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs b/examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs new file mode 100644 index 0000000..b3c172e --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs @@ -0,0 +1,56 @@ +using System.Text; +using Microsoft.AspNetCore.Mvc; + +namespace HttpClientToCurl.Sample.InSpecific.Controllers; + +[ApiController] +[Route("[controller]")] +public class MyController(IHttpClientFactory httpClientFactory) : ControllerBase +{ + private readonly IHttpClientFactory _httpClientFactory = httpClientFactory; + + [HttpGet] + public async Task Send() + { + string apiUrl = "https://jsonplaceholder.typicode.com/posts"; + + try + { + // Create a sample JSON payload + string jsonPayload = + $"{{\"title\":\"New Post\",\"body\":\"This is the body of the new post\",\"userId\":1}}"; + + // Create HttpRequestMessage with the POST verb + HttpRequestMessage request = new(HttpMethod.Post, apiUrl); + + // Set up the request headers + request.Headers.Add("Authorization", "Bearer YourAccessToken"); // Add any necessary headers + + // Set the request content with the JSON payload + request.Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + + // Log the curl command for debugging or testing. + // This generates a curl command that can be imported into Postman. + // Use it to check and compare against all the requirements. + + // Send the request + HttpResponseMessage response = await _httpClientFactory.CreateClient("my-client").SendAsync(request); + + // Check if the request was successful (status code 200-299) + if (response.IsSuccessStatusCode) + { + // Read and print the response content as a string + string responseBody = await response.Content.ReadAsStringAsync(); + Console.WriteLine("Response from the API:\n" + responseBody); + } + else + { + Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"Exception: {ex.Message}"); + } + } +} diff --git a/examples/HttpClientToCurl.Sample.InSpecific/HttpClientToCurl.Sample.InSpecific.csproj b/examples/HttpClientToCurl.Sample.InSpecific/HttpClientToCurl.Sample.InSpecific.csproj new file mode 100644 index 0000000..100f3d9 --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InSpecific/HttpClientToCurl.Sample.InSpecific.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + enable + enable + + + + + + + diff --git a/examples/HttpClientToCurl.Sample.InSpecific/Program.cs b/examples/HttpClientToCurl.Sample.InSpecific/Program.cs new file mode 100644 index 0000000..1d10b9e --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InSpecific/Program.cs @@ -0,0 +1,23 @@ +using HttpClientToCurl.Config.Others; +using HttpClientToCurl.HttpMessageHandlers; +using static HttpClientToCurl.Extensions.ServiceCollectionExtensions; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddControllers(); +builder.Services.AddHttpClientToCurl(config => +{ + config.ShowMode = ShowMode.Console | ShowMode.File; + config.NeedAddDefaultHeaders = true; + config.ConsoleEnableCodeBeautification = true; + config.FileConfigPath = "C:\\Users\\Public"; + config.FileConfigFileName = "curl_commands"; +}, false); +builder.Services.AddHttpClient("my-client") + .AddHttpMessageHandler(); + +var app = builder.Build(); + +app.UseHttpsRedirection(); +app.UseAuthorization(); +app.MapControllers(); +app.Run(); diff --git a/examples/HttpClientToCurl.Sample.InSpecific/Properties/launchSettings.json b/examples/HttpClientToCurl.Sample.InSpecific/Properties/launchSettings.json new file mode 100644 index 0000000..c584543 --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InSpecific/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5062", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7001;http://localhost:5062", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/examples/HttpClientToCurl.Sample.InSpecific/appsettings.Development.json b/examples/HttpClientToCurl.Sample.InSpecific/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InSpecific/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/examples/HttpClientToCurl.Sample.InSpecific/appsettings.json b/examples/HttpClientToCurl.Sample.InSpecific/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/examples/HttpClientToCurl.Sample.InSpecific/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From 50894e9ad6315ec4631916ac36d3b14106f352e2 Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Thu, 30 Oct 2025 23:40:44 +0330 Subject: [PATCH 08/10] Use option monitor for configurating global and specific usages --- .../Program.cs | 11 +---- .../appsettings.json | 20 +++++++- .../Controllers/MyController.cs | 15 +++++- .../Program.cs | 16 ++----- .../appsettings.json | 20 +++++++- src/HttpClientToCurl/Config/CompositConfig.cs | 21 +++++++++ src/HttpClientToCurl/Config/GlobalConfig.cs | 27 ----------- .../Extensions/ServiceCollectionExtensions.cs | 47 +++++++++++++------ src/HttpClientToCurl/HttpClientToCurl.csproj | 1 + .../CurlGeneratorHttpMessageHandler.cs | 43 ++++++++++------- 10 files changed, 136 insertions(+), 85 deletions(-) create mode 100644 src/HttpClientToCurl/Config/CompositConfig.cs delete mode 100644 src/HttpClientToCurl/Config/GlobalConfig.cs diff --git a/examples/HttpClientToCurl.Sample.InGlobal/Program.cs b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs index 820b7c6..bd5b837 100644 --- a/examples/HttpClientToCurl.Sample.InGlobal/Program.cs +++ b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs @@ -1,16 +1,9 @@ -using HttpClientToCurl.Config.Others; using static HttpClientToCurl.Extensions.ServiceCollectionExtensions; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); -builder.Services.AddHttpClientToCurl(config => -{ - config.ShowMode = ShowMode.Console | ShowMode.File; - config.NeedAddDefaultHeaders = true; - config.ConsoleEnableCodeBeautification = true; - config.FileConfigPath = "C:\\Users\\Public"; - config.FileConfigFileName = "curl_commands"; -}); + +builder.Services.AddHttpClientToCurlInGeneralMode(builder.Configuration); builder.Services.AddHttpClient(); var app = builder.Build(); diff --git a/examples/HttpClientToCurl.Sample.InGlobal/appsettings.json b/examples/HttpClientToCurl.Sample.InGlobal/appsettings.json index 10f68b8..279e909 100644 --- a/examples/HttpClientToCurl.Sample.InGlobal/appsettings.json +++ b/examples/HttpClientToCurl.Sample.InGlobal/appsettings.json @@ -5,5 +5,23 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "HttpClientToCurl": { + "TurnOnAll": true, + + "ShowOnConsole": { + "TurnOn": true, //CAUTION: It will be applied when TurnOnAll is 'true' + "NeedAddDefaultHeaders": true, + "EnableCompression": false, + "EnableCodeBeautification": true + }, + + "SaveToFile": { + "TurnOn": true, //CAUTION: It will be applied when TurnOnAll is 'true' + "NeedAddDefaultHeaders": true, + "EnableCompression": false, + "Filename": "curl_commands", + "Path": "C:\\Users\\Public" + } + } } diff --git a/examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs b/examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs index b3c172e..0094dbc 100644 --- a/examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs +++ b/examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs @@ -9,8 +9,19 @@ public class MyController(IHttpClientFactory httpClientFactory) : ControllerBase { private readonly IHttpClientFactory _httpClientFactory = httpClientFactory; - [HttpGet] + [HttpGet("send-and-show-curl")] + public async Task SendAndShowCurl() + { + await SendRemoteRequest("my-client1"); + } + + [HttpGet("send")] public async Task Send() + { + await SendRemoteRequest("my-client2"); + } + + private async Task SendRemoteRequest(string httpClientName) { string apiUrl = "https://jsonplaceholder.typicode.com/posts"; @@ -34,7 +45,7 @@ public async Task Send() // Use it to check and compare against all the requirements. // Send the request - HttpResponseMessage response = await _httpClientFactory.CreateClient("my-client").SendAsync(request); + HttpResponseMessage response = await _httpClientFactory.CreateClient(httpClientName).SendAsync(request); // Check if the request was successful (status code 200-299) if (response.IsSuccessStatusCode) diff --git a/examples/HttpClientToCurl.Sample.InSpecific/Program.cs b/examples/HttpClientToCurl.Sample.InSpecific/Program.cs index 1d10b9e..3a6d93b 100644 --- a/examples/HttpClientToCurl.Sample.InSpecific/Program.cs +++ b/examples/HttpClientToCurl.Sample.InSpecific/Program.cs @@ -1,19 +1,11 @@ -using HttpClientToCurl.Config.Others; -using HttpClientToCurl.HttpMessageHandlers; using static HttpClientToCurl.Extensions.ServiceCollectionExtensions; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); -builder.Services.AddHttpClientToCurl(config => -{ - config.ShowMode = ShowMode.Console | ShowMode.File; - config.NeedAddDefaultHeaders = true; - config.ConsoleEnableCodeBeautification = true; - config.FileConfigPath = "C:\\Users\\Public"; - config.FileConfigFileName = "curl_commands"; -}, false); -builder.Services.AddHttpClient("my-client") - .AddHttpMessageHandler(); + +builder.Services.AddHttpClientToCurl(builder.Configuration); +builder.Services.AddHttpClient("my-client1", showCurl: true); +builder.Services.AddHttpClient("my-client2"); var app = builder.Build(); diff --git a/examples/HttpClientToCurl.Sample.InSpecific/appsettings.json b/examples/HttpClientToCurl.Sample.InSpecific/appsettings.json index 10f68b8..279e909 100644 --- a/examples/HttpClientToCurl.Sample.InSpecific/appsettings.json +++ b/examples/HttpClientToCurl.Sample.InSpecific/appsettings.json @@ -5,5 +5,23 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "HttpClientToCurl": { + "TurnOnAll": true, + + "ShowOnConsole": { + "TurnOn": true, //CAUTION: It will be applied when TurnOnAll is 'true' + "NeedAddDefaultHeaders": true, + "EnableCompression": false, + "EnableCodeBeautification": true + }, + + "SaveToFile": { + "TurnOn": true, //CAUTION: It will be applied when TurnOnAll is 'true' + "NeedAddDefaultHeaders": true, + "EnableCompression": false, + "Filename": "curl_commands", + "Path": "C:\\Users\\Public" + } + } } diff --git a/src/HttpClientToCurl/Config/CompositConfig.cs b/src/HttpClientToCurl/Config/CompositConfig.cs new file mode 100644 index 0000000..d610b76 --- /dev/null +++ b/src/HttpClientToCurl/Config/CompositConfig.cs @@ -0,0 +1,21 @@ +namespace HttpClientToCurl.Config; + +public sealed class CompositConfig +{ + /// + /// Set true to create curl output; false to disable it. Default is true. + /// + public bool TurnOnAll { get; set; } = true; + + /// + /// Set true to show curl on the console; false to disable it. Default is true. + /// If TurnOnAll is set to false, it will be ignored. + /// + public ConsoleConfig ShowOnConsole { get; set; } + + /// + /// Set true to save the curl file; false to disable it. Default is true. + /// If TurnOnAll is set to false, it will be ignored. + /// + public FileConfig SaveToFile { get; set; } +} diff --git a/src/HttpClientToCurl/Config/GlobalConfig.cs b/src/HttpClientToCurl/Config/GlobalConfig.cs deleted file mode 100644 index 8378063..0000000 --- a/src/HttpClientToCurl/Config/GlobalConfig.cs +++ /dev/null @@ -1,27 +0,0 @@ -using HttpClientToCurl.Config.Others; - -namespace HttpClientToCurl.Config; - -public sealed class GlobalConfig -{ - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0032:Use auto property", Justification = "")] - private ShowMode _showMode; - - public ShowMode ShowMode - { - get => _showMode; - set - { - if (value is not ShowMode.None && value.HasFlag(ShowMode.None)) - { - throw new ArgumentException("ShowMode.None cannot be combined with other flags."); - } - _showMode = value; - } - } - public bool NeedAddDefaultHeaders { get; set; } = true; - public bool ConsoleEnableCodeBeautification { get; set; } = false; - public bool ConsoleEnableCompression { get; set; } = false; - public string FileConfigFileName { get; set; } - public string FileConfigPath { get; set; } -} diff --git a/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs b/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs index ce64332..80ddb98 100644 --- a/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs +++ b/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs @@ -1,6 +1,6 @@ using HttpClientToCurl.Config; -using HttpClientToCurl.Config.Others; using HttpClientToCurl.HttpMessageHandlers; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Http; @@ -9,27 +9,44 @@ namespace HttpClientToCurl.Extensions; public static class ServiceCollectionExtensions { /// - /// Generating curl script of all HTTP requests. + /// Generating curl script for all HTTP requests. /// By default, show it in the IDE console. /// - /// Optional - /// Apply for all http requests in the application or not. Default is true. - public static void AddHttpClientToCurl( - this IServiceCollection services, - Action configAction = null, - bool isGlobal = true) + public static void AddHttpClientToCurlInGeneralMode( + this IServiceCollection services, + IConfiguration configuration) { - configAction ??= config => config.ShowMode = ShowMode.Console; + AddServices(services, configuration); + services.Add(ServiceDescriptor.Transient()); + } - var config = new GlobalConfig(); - configAction?.Invoke(config); + /// + /// Generating curl script for specific http client + /// + /// + /// + public static void AddHttpClientToCurl( + this IServiceCollection services, + IConfiguration configuration) + { + AddServices(services, configuration); + } - services.AddSingleton(config); - services.AddTransient(); + public static IHttpClientBuilder AddHttpClient(this IServiceCollection services, string name, bool showCurl = false) + { + var httpClientBuilder = HttpClientFactoryServiceCollectionExtensions.AddHttpClient(services, name); - if (isGlobal) + if (showCurl) { - services.Add(ServiceDescriptor.Transient()); + httpClientBuilder.AddHttpMessageHandler(); } + + return httpClientBuilder; + } + + private static void AddServices(IServiceCollection services, IConfiguration configuration) + { + services.Configure(configuration.GetSection("HttpClientToCurl")); + services.AddTransient(); } } diff --git a/src/HttpClientToCurl/HttpClientToCurl.csproj b/src/HttpClientToCurl/HttpClientToCurl.csproj index 79642c0..4cbe8fc 100644 --- a/src/HttpClientToCurl/HttpClientToCurl.csproj +++ b/src/HttpClientToCurl/HttpClientToCurl.csproj @@ -25,6 +25,7 @@ + diff --git a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs index 4e8c859..a19ecd4 100644 --- a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs +++ b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs @@ -1,35 +1,42 @@ using HttpClientToCurl.Config; -using HttpClientToCurl.Config.Others; using HttpClientToCurl.Extensions; +using Microsoft.Extensions.Options; namespace HttpClientToCurl.HttpMessageHandlers; -public class CurlGeneratorHttpMessageHandler(GlobalConfig config) : DelegatingHandler +public class CurlGeneratorHttpMessageHandler(IOptionsMonitor monitorConfig) : DelegatingHandler { + private readonly IOptionsMonitor _monitorConfig = monitorConfig; + protected override Task SendAsync( HttpRequestMessage httpRequestMessage, CancellationToken cancellationToken) { - if (config.ShowMode.HasFlag(ShowMode.Console)) + var config = _monitorConfig.CurrentValue; + if (config.TurnOnAll) { - httpRequestMessage.GenerateCurlInConsole(httpRequestMessage.RequestUri, consoleConfig => + if (config.ShowOnConsole.TurnOn) { - consoleConfig.TurnOn = true; - consoleConfig.EnableCodeBeautification = config.ConsoleEnableCodeBeautification; - consoleConfig.EnableCompression = config.ConsoleEnableCompression; - consoleConfig.NeedAddDefaultHeaders = config.NeedAddDefaultHeaders; - }); - } + httpRequestMessage.GenerateCurlInConsole(httpRequestMessage.RequestUri, consoleConfig => + { + consoleConfig.TurnOn = true; + consoleConfig.EnableCodeBeautification = config.ShowOnConsole.EnableCodeBeautification; + consoleConfig.EnableCompression = config.ShowOnConsole.EnableCompression; + consoleConfig.NeedAddDefaultHeaders = config.ShowOnConsole.NeedAddDefaultHeaders; + }); + } - if (config.ShowMode.HasFlag(ShowMode.File)) - { - httpRequestMessage.GenerateCurlInFile(httpRequestMessage.RequestUri, fileConfig => + if (config.SaveToFile.TurnOn) { - fileConfig.TurnOn = true; - fileConfig.Filename = config.FileConfigFileName; - fileConfig.Path = config.FileConfigPath; - fileConfig.NeedAddDefaultHeaders = config.NeedAddDefaultHeaders; - }); + httpRequestMessage.GenerateCurlInFile(httpRequestMessage.RequestUri, fileConfig => + { + fileConfig.TurnOn = true; + fileConfig.EnableCompression = config.SaveToFile.EnableCompression; + fileConfig.NeedAddDefaultHeaders = config.SaveToFile.NeedAddDefaultHeaders; + fileConfig.Path = config.SaveToFile.Path; + fileConfig.Filename = config.SaveToFile.Filename; + }); + } } var response = base.SendAsync(httpRequestMessage, cancellationToken); From 6a43b02c0dd21ab4773b0ae3ecbe9be77e336b0a Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Fri, 31 Oct 2025 11:13:59 +0330 Subject: [PATCH 09/10] =?UTF-8?q?Check=20configs=20nullability=20=E2=96=B6?= =?UTF-8?q?=EF=B8=8F=20CurlGeneratorHttpMessageHandler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs index a19ecd4..ea187b3 100644 --- a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs +++ b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs @@ -15,7 +15,7 @@ protected override Task SendAsync( var config = _monitorConfig.CurrentValue; if (config.TurnOnAll) { - if (config.ShowOnConsole.TurnOn) + if (config.ShowOnConsole?.TurnOn ?? false) { httpRequestMessage.GenerateCurlInConsole(httpRequestMessage.RequestUri, consoleConfig => { @@ -26,7 +26,7 @@ protected override Task SendAsync( }); } - if (config.SaveToFile.TurnOn) + if (config.SaveToFile?.TurnOn ?? false) { httpRequestMessage.GenerateCurlInFile(httpRequestMessage.RequestUri, fileConfig => { From daaa437861c4ce143dc6d39635cf792172836b97 Mon Sep 17 00:00:00 2001 From: Amirhossein Enayati Date: Fri, 31 Oct 2025 12:45:20 +0330 Subject: [PATCH 10/10] Remove extra code --- src/HttpClientToCurl/Config/Others/ShowMode.cs | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/HttpClientToCurl/Config/Others/ShowMode.cs diff --git a/src/HttpClientToCurl/Config/Others/ShowMode.cs b/src/HttpClientToCurl/Config/Others/ShowMode.cs deleted file mode 100644 index 5819520..0000000 --- a/src/HttpClientToCurl/Config/Others/ShowMode.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace HttpClientToCurl.Config.Others; - -[Flags] -public enum ShowMode -{ - None = 1, - Console = 2, - File = 4 -}