diff --git a/.lutignore b/.lutignore
new file mode 100644
index 0000000..6108a61
--- /dev/null
+++ b/.lutignore
@@ -0,0 +1,98 @@
+## The .lutignore file is used by Live Unit Testing to ignore Visual Studio temporary files, build results,
+## and files generated by popular Visual Studio add-ons when creating a private copy of the source tree that
+## Live Unit Testing uses for its build.
+##
+## This file has same format as git's .gitignore file (https://git-scm.com/docs/gitignore). In fact, in the
+## case where a .lutignore file is not found, but a .gitignore file is found, Live Unit Testing will use the
+## .gitignore file directly for the above purpose.
+
+# User-specific files
+*.suo
+*.user
+*.userprefs
+*.sln.docstates
+.vs/
+.vscode/
+.packages/
+.dotnet/
+.tools/
+.idea/
+
+# Build results
+[Dd]ebug/
+[Rr]elease/
+[Bb]inaries/
+[Bb]in/
+[Oo]bj/
+x64/
+TestResults/
+
+# Debug artifacts
+launchSettings.json
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.Publish.xml
+
+# NuGet
+packages/
+[Nn]u[Gg]et.exe
+*-packages.config
+*.nuget.props
+*.nuget.targets
+project.lock.json
+msbuild.binlog
+*.project.lock.json
+
+# Miscellaneous
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.wrn
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.scc
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.[Pp]ublish.xml
+*.pfx
+*.publishsettings
+
+# Cache and temp files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.opendb
+*.VC.db
+AppPackages/
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings
+$RECYCLE.BIN/
+.DS_Store
+*wpftmp.*
diff --git a/HttpClientToCurlGenerator.lutconfig b/HttpClientToCurlGenerator.lutconfig
new file mode 100644
index 0000000..596a860
--- /dev/null
+++ b/HttpClientToCurlGenerator.lutconfig
@@ -0,0 +1,6 @@
+
+
+ true
+ true
+ 180000
+
\ No newline at end of file
diff --git a/HttpClientToCurlGenerator.sln b/HttpClientToCurlGenerator.sln
index 09a4b58..34648e8 100644
--- a/HttpClientToCurlGenerator.sln
+++ b/HttpClientToCurlGenerator.sln
@@ -5,8 +5,6 @@ VisualStudioVersion = 17.7.34221.43
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpClientToCurl", "src\HttpClientToCurl\HttpClientToCurl.csproj", "{18B3309D-B84C-453D-8EF7-16CA9E58F5DC}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpClientToCurlGeneratorTest", "tests\HttpClientToCurlTest\HttpClientToCurlTest.csproj", "{BF3321A5-A590-44DD-BA5D-44978D9B6125}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{A8574DB9-8411-4F81-A82E-F97AD00EF8AF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpClientToCurl.Sample.InConsole", "examples\HttpClientToCurl.Sample.InConsole\HttpClientToCurl.Sample.InConsole.csproj", "{323022D2-AAA7-443B-895C-77F5B1634D68}"
@@ -25,7 +23,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solutionItems", "solutionIt
pre-push = pre-push
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpRequestMessageToCurlGeneratorTest", "tests\HttpRequestMessageToCurlTest\HttpRequestMessageToCurlTest.csproj", "{007CA9E0-CDF0-4375-8E8C-A24C9A7BF531}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpClientToCurl.Sample.InGlobal", "examples\HttpClientToCurl.Sample.InGlobal\HttpClientToCurl.Sample.InGlobal.csproj", "{5A8427BC-0821-E973-7221-263D13156248}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpClientToCurlTest", "tests\HttpClientToCurlTest\HttpClientToCurlTest.csproj", "{8CC76F1F-5845-D81E-5E9A-113F913A444B}"
+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
@@ -37,10 +41,6 @@ Global
{18B3309D-B84C-453D-8EF7-16CA9E58F5DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18B3309D-B84C-453D-8EF7-16CA9E58F5DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18B3309D-B84C-453D-8EF7-16CA9E58F5DC}.Release|Any CPU.Build.0 = Release|Any CPU
- {BF3321A5-A590-44DD-BA5D-44978D9B6125}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {BF3321A5-A590-44DD-BA5D-44978D9B6125}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {BF3321A5-A590-44DD-BA5D-44978D9B6125}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {BF3321A5-A590-44DD-BA5D-44978D9B6125}.Release|Any CPU.Build.0 = Release|Any CPU
{323022D2-AAA7-443B-895C-77F5B1634D68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{323022D2-AAA7-443B-895C-77F5B1634D68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{323022D2-AAA7-443B-895C-77F5B1634D68}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -53,21 +53,35 @@ Global
{403B236B-D7D8-43FB-B47E-DCCAF8BA96C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{403B236B-D7D8-43FB-B47E-DCCAF8BA96C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{403B236B-D7D8-43FB-B47E-DCCAF8BA96C4}.Release|Any CPU.Build.0 = Release|Any CPU
- {007CA9E0-CDF0-4375-8E8C-A24C9A7BF531}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {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
+ {8CC76F1F-5845-D81E-5E9A-113F913A444B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8CC76F1F-5845-D81E-5E9A-113F913A444B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8CC76F1F-5845-D81E-5E9A-113F913A444B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8CC76F1F-5845-D81E-5E9A-113F913A444B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {69E31075-F14E-1DE2-1D6E-D934A5C0480F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {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
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{18B3309D-B84C-453D-8EF7-16CA9E58F5DC} = {D3967ABF-F7C6-4432-9B67-A3F804CBC3E7}
- {BF3321A5-A590-44DD-BA5D-44978D9B6125} = {E36BF269-7F5D-4DE7-99B0-14567F9CD6B3}
{323022D2-AAA7-443B-895C-77F5B1634D68} = {A8574DB9-8411-4F81-A82E-F97AD00EF8AF}
{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}
+ {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.InConsole/ApiCaller.cs b/examples/HttpClientToCurl.Sample.InConsole/ApiCaller.cs
index 5e8f197..2e58582 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 8df32d5..38aaabd 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.InGlobal/Controllers/MyController.cs b/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs
new file mode 100644
index 0000000..25600a8
--- /dev/null
+++ b/examples/HttpClientToCurl.Sample.InGlobal/Controllers/MyController.cs
@@ -0,0 +1,56 @@
+using System.Text;
+using Microsoft.AspNetCore.Mvc;
+
+namespace HttpClientToCurl.Sample.InGlobal.Controllers;
+
+[ApiController]
+[Route("[controller]")]
+public class MyController(HttpClient httpClient) : ControllerBase
+{
+ private readonly 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..99a0baf
--- /dev/null
+++ b/examples/HttpClientToCurl.Sample.InGlobal/HttpClientToCurl.Sample.InGlobal.csproj
@@ -0,0 +1,14 @@
+
+
+
+ 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..bd5b837
--- /dev/null
+++ b/examples/HttpClientToCurl.Sample.InGlobal/Program.cs
@@ -0,0 +1,14 @@
+using static HttpClientToCurl.Extensions.ServiceCollectionExtensions;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Services.AddControllers();
+
+builder.Services.AddHttpClientToCurlInGeneralMode(builder.Configuration);
+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..279e909
--- /dev/null
+++ b/examples/HttpClientToCurl.Sample.InGlobal/appsettings.json
@@ -0,0 +1,27 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "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
new file mode 100644
index 0000000..0094dbc
--- /dev/null
+++ b/examples/HttpClientToCurl.Sample.InSpecific/Controllers/MyController.cs
@@ -0,0 +1,67 @@
+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("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";
+
+ 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(httpClientName).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..3a6d93b
--- /dev/null
+++ b/examples/HttpClientToCurl.Sample.InSpecific/Program.cs
@@ -0,0 +1,15 @@
+using static HttpClientToCurl.Extensions.ServiceCollectionExtensions;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Services.AddControllers();
+
+builder.Services.AddHttpClientToCurl(builder.Configuration);
+builder.Services.AddHttpClient("my-client1", showCurl: true);
+builder.Services.AddHttpClient("my-client2");
+
+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..279e909
--- /dev/null
+++ b/examples/HttpClientToCurl.Sample.InSpecific/appsettings.json
@@ -0,0 +1,27 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "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.InString/ApiCaller.cs b/examples/HttpClientToCurl.Sample.InString/ApiCaller.cs
index ccfeb20..9db59fd 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/examples/HttpClientToCurl.Sample.InString/HttpClientToCurl.Sample.InString.csproj b/examples/HttpClientToCurl.Sample.InString/HttpClientToCurl.Sample.InString.csproj
index f1bc580..837995e 100644
--- a/examples/HttpClientToCurl.Sample.InString/HttpClientToCurl.Sample.InString.csproj
+++ b/examples/HttpClientToCurl.Sample.InString/HttpClientToCurl.Sample.InString.csproj
@@ -11,4 +11,8 @@
+
+
+
+
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/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/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs b/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs
new file mode 100644
index 0000000..80ddb98
--- /dev/null
+++ b/src/HttpClientToCurl/Extensions/ServiceCollectionExtensions.cs
@@ -0,0 +1,52 @@
+using HttpClientToCurl.Config;
+using HttpClientToCurl.HttpMessageHandlers;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Http;
+
+namespace HttpClientToCurl.Extensions;
+
+public static class ServiceCollectionExtensions
+{
+ ///
+ /// Generating curl script for all HTTP requests.
+ /// By default, show it in the IDE console.
+ ///
+ public static void AddHttpClientToCurlInGeneralMode(
+ this IServiceCollection services,
+ IConfiguration configuration)
+ {
+ AddServices(services, configuration);
+ services.Add(ServiceDescriptor.Transient());
+ }
+
+ ///
+ /// Generating curl script for specific http client
+ ///
+ ///
+ ///
+ public static void AddHttpClientToCurl(
+ this IServiceCollection services,
+ IConfiguration configuration)
+ {
+ AddServices(services, configuration);
+ }
+
+ public static IHttpClientBuilder AddHttpClient(this IServiceCollection services, string name, bool showCurl = false)
+ {
+ var httpClientBuilder = HttpClientFactoryServiceCollectionExtensions.AddHttpClient(services, name);
+
+ if (showCurl)
+ {
+ 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 68c7394..4cbe8fc 100644
--- a/src/HttpClientToCurl/HttpClientToCurl.csproj
+++ b/src/HttpClientToCurl/HttpClientToCurl.csproj
@@ -1,4 +1,4 @@
-
+
Amin Golmahalleh
@@ -22,4 +22,10 @@
+
+
+
+
+
+
diff --git a/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs
new file mode 100644
index 0000000..ea187b3
--- /dev/null
+++ b/src/HttpClientToCurl/HttpMessageHandlers/CurlGeneratorHttpMessageHandler.cs
@@ -0,0 +1,45 @@
+using HttpClientToCurl.Config;
+using HttpClientToCurl.Extensions;
+using Microsoft.Extensions.Options;
+
+namespace HttpClientToCurl.HttpMessageHandlers;
+
+public class CurlGeneratorHttpMessageHandler(IOptionsMonitor monitorConfig) : DelegatingHandler
+{
+ private readonly IOptionsMonitor _monitorConfig = monitorConfig;
+
+ protected override Task SendAsync(
+ HttpRequestMessage httpRequestMessage,
+ CancellationToken cancellationToken)
+ {
+ var config = _monitorConfig.CurrentValue;
+ if (config.TurnOnAll)
+ {
+ if (config.ShowOnConsole?.TurnOn ?? false)
+ {
+ 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.SaveToFile?.TurnOn ?? false)
+ {
+ 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);
+ return response;
+ }
+}
diff --git a/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs b/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs
new file mode 100644
index 0000000..fa35ae5
--- /dev/null
+++ b/src/HttpClientToCurl/HttpMessageHandlers/HttpMessageHandlerAppender.cs
@@ -0,0 +1,13 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Http;
+
+namespace HttpClientToCurl.HttpMessageHandlers;
+public class HttpMessageHandlerAppender(IServiceProvider serviceProvider) : IHttpMessageHandlerBuilderFilter
+{
+ public Action Configure(Action next) => builder =>
+ {
+ next(builder);
+ var handler = serviceProvider.GetRequiredService();
+ builder.AdditionalHandlers.Add(handler);
+ };
+}
diff --git a/tests/HttpClientToCurlTest/FunctionalTest/SuccessScenariosTests.cs b/tests/HttpClientToCurlTest/FunctionalTest/SuccessScenariosTests.cs
index f8c7d0c..088c915 100644
--- a/tests/HttpClientToCurlTest/FunctionalTest/SuccessScenariosTests.cs
+++ b/tests/HttpClientToCurlTest/FunctionalTest/SuccessScenariosTests.cs
@@ -3,7 +3,7 @@
using System.Net.Mime;
using System.Text;
using FluentAssertions;
-using HttpClientToCurl;
+using HttpClientToCurl.Extensions;
using HttpClientToCurl.Utility;
using Microsoft.AspNetCore.WebUtilities;
using Xunit;
diff --git a/tests/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs b/tests/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs
index ae88a67..c933c97 100644
--- a/tests/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs
+++ b/tests/HttpRequestMessageToCurlTest/FunctionalTest/SuccessScenariosTests.cs
@@ -1,7 +1,7 @@
using System.Net.Mime;
using System.Text;
using FluentAssertions;
-using HttpClientToCurl;
+using HttpClientToCurl.Extensions;
using HttpClientToCurl.Utility;
using Microsoft.AspNetCore.WebUtilities;
using Xunit;