diff --git a/DebugProbe.AspNetCore.Tests/Rendering/HtmlRendererTests.cs b/DebugProbe.AspNetCore.Tests/Rendering/HtmlRendererTests.cs index 421699b..f343bd5 100644 --- a/DebugProbe.AspNetCore.Tests/Rendering/HtmlRendererTests.cs +++ b/DebugProbe.AspNetCore.Tests/Rendering/HtmlRendererTests.cs @@ -64,7 +64,7 @@ public void Html_encoding_escapes_untrusted_values() var entry = CreateEntry(); entry.Method = ""; entry.Path = "/orders/"; - entry.Headers["X-Unsafe"] = ""; + entry.RequestHeaders["X-Unsafe"] = ""; var html = HtmlRenderer.RenderDetailsPage( entry, @@ -94,7 +94,15 @@ private static DebugEntry CreateEntry() DurationMs = 12, Timestamp = new DateTimeOffset(2026, 1, 2, 3, 4, 5, TimeSpan.Zero), RequestTimeUtc = new DateTimeOffset(2026, 1, 2, 3, 4, 5, TimeSpan.Zero), - Headers = new Dictionary { ["X-Test"] = "yes" } + RequestHeaders = new Dictionary + { + ["X-Test"] = "yes" + }, + + ResponseHeaders = new Dictionary + { + ["Content-Type"] = "application/json" + } }; } diff --git a/DebugProbe.AspNetCore/Assets/html/details.html b/DebugProbe.AspNetCore/Assets/html/details.html index aacd832..8259448 100644 --- a/DebugProbe.AspNetCore/Assets/html/details.html +++ b/DebugProbe.AspNetCore/Assets/html/details.html @@ -90,6 +90,7 @@

{{method}} {{path}}

+

Request URL

@@ -104,6 +105,20 @@

Request URL

{{requestUrl}}
+
+

Request Headers

+ +
+ + HEADERS + +
+
+ +
+ +
{{requestHeaders}}
+

Request Body

@@ -119,6 +134,20 @@

Request Body

{{request}}
+
+

Response Headers

+ +
+ + HEADERS + +
+
+ +
+ +
{{responseHeaders}}
+

Response Body

diff --git a/DebugProbe.AspNetCore/DebugProbe.AspNetCore.csproj b/DebugProbe.AspNetCore/DebugProbe.AspNetCore.csproj index d06c99b..64996c4 100644 --- a/DebugProbe.AspNetCore/DebugProbe.AspNetCore.csproj +++ b/DebugProbe.AspNetCore/DebugProbe.AspNetCore.csproj @@ -41,11 +41,11 @@ - - - - - + + + + + diff --git a/DebugProbe.AspNetCore/Internal/Rendering/HtmlRenderer.cs b/DebugProbe.AspNetCore/Internal/Rendering/HtmlRenderer.cs index c1739c6..46a9c00 100644 --- a/DebugProbe.AspNetCore/Internal/Rendering/HtmlRenderer.cs +++ b/DebugProbe.AspNetCore/Internal/Rendering/HtmlRenderer.cs @@ -43,8 +43,11 @@ public static string RenderIndexPage(List items) public static string RenderDetailsPage(DebugEntry x, DebugEnvironment e, string req, string res) { - var headers = string.Join("", x.Headers.Select(h => - $"{Encode(h.Key)}{Encode(h.Value)}")); + //var headers = string.Join("", x.Reqe.Select(h => + // $"{Encode(h.Key)}{Encode(h.Value)}")); + + var requestHeaders = string.Join(Environment.NewLine, x.RequestHeaders.Select(h => $"{h.Key}: {h.Value}")); + var responseHeaders = string.Join(Environment.NewLine, x.ResponseHeaders.Select(h => $"{h.Key}: {h.Value}")); var pathWithQuery = string.IsNullOrEmpty(x.Query) ? x.Path @@ -79,13 +82,15 @@ public static string RenderDetailsPage(DebugEntry x, DebugEnvironment e, string .Replace("{{requestUrl}}", Encode(string.IsNullOrEmpty(x.RequestUrl) ? "" : x.RequestUrl)) .Replace("{{requestType}}", GetPayloadType(req)) .Replace("{{requestTypeClass}}", GetPayloadTypeClass(req)) + .Replace("{{requestHeaders}}", Encode(requestHeaders)) .Replace("{{request}}", Encode(string.IsNullOrEmpty(req) ? "" : req)) .Replace("{{responseType}}", GetPayloadType(res)) .Replace("{{responseTypeClass}}", GetPayloadTypeClass(res)) - .Replace("{{response}}", Encode(string.IsNullOrEmpty(res) ? "" : res)) + .Replace("{{responseHeaders}}", Encode(responseHeaders)) + .Replace("{{response}}", Encode(string.IsNullOrEmpty(res) ? "" : res)); - .Replace("{{headers}}", headers); + //.Replace("{{headers}}", headers); return BuildLayout(content); } diff --git a/DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs b/DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs index 464ca93..14c2cef 100644 --- a/DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs +++ b/DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs @@ -95,6 +95,11 @@ public async Task Invoke(HttpContext context, DebugEntryStore store) RequestSize = context.Request.ContentLength ?? Encoding.UTF8.GetByteCount(requestBody), ResponseSize = Encoding.UTF8.GetByteCount(responseBody), + + // Request Headers + RequestHeaders = context.Request.Headers.ToDictionary(x => x.Key, x => + SensitiveHeaders.Contains(x.Key) ? "[REDACTED]" : x.Value.ToString()), + // Request RequestUrl = $"{context.Request.Scheme}://{context.Request.Host}" + $"{context.Request.Path}{context.Request.QueryString}", @@ -103,10 +108,9 @@ public async Task Invoke(HttpContext context, DebugEntryStore store) // Response ResponseBody = Trim(responseBody, maxBodySize), - // Headers - Headers = context.Request.Headers.ToDictionary( - x => x.Key, - x => SensitiveHeaders.Contains(x.Key) ? "[REDACTED]" : x.Value.ToString()), + // Response Headers + ResponseHeaders = context.Response.Headers.ToDictionary(x => x.Key, x => + SensitiveHeaders.Contains(x.Key)? "[REDACTED]" : x.Value.ToString()), // Other Timestamp = DateTime.UtcNow, diff --git a/DebugProbe.AspNetCore/Models/DebugEntry.cs b/DebugProbe.AspNetCore/Models/DebugEntry.cs index 3ffa07d..e6eb787 100644 --- a/DebugProbe.AspNetCore/Models/DebugEntry.cs +++ b/DebugProbe.AspNetCore/Models/DebugEntry.cs @@ -20,7 +20,8 @@ public class DebugEntry public string ResponseBody { get; set; } = default!; // Headers - public Dictionary Headers { get; set; } = new(); + public Dictionary RequestHeaders { get; set; } = new(); + public Dictionary ResponseHeaders { get; set; } = new(); // Metadata public DateTimeOffset Timestamp { get; set; }