Skip to content

Commit 36f2869

Browse files
feat: capture and display request and response headers
Adds request and response headers support to DebugProbe.
2 parents 13f704a + 2dfaa29 commit 36f2869

6 files changed

Lines changed: 63 additions & 16 deletions

File tree

DebugProbe.AspNetCore.Tests/Rendering/HtmlRendererTests.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public void Html_encoding_escapes_untrusted_values()
6464
var entry = CreateEntry();
6565
entry.Method = "<script>alert(1)</script>";
6666
entry.Path = "/orders/<bad>";
67-
entry.Headers["X-Unsafe"] = "<img src=x onerror=alert(1)>";
67+
entry.RequestHeaders["X-Unsafe"] = "<img src=x onerror=alert(1)>";
6868

6969
var html = HtmlRenderer.RenderDetailsPage(
7070
entry,
@@ -94,7 +94,15 @@ private static DebugEntry CreateEntry()
9494
DurationMs = 12,
9595
Timestamp = new DateTimeOffset(2026, 1, 2, 3, 4, 5, TimeSpan.Zero),
9696
RequestTimeUtc = new DateTimeOffset(2026, 1, 2, 3, 4, 5, TimeSpan.Zero),
97-
Headers = new Dictionary<string, string> { ["X-Test"] = "yes" }
97+
RequestHeaders = new Dictionary<string, string>
98+
{
99+
["X-Test"] = "yes"
100+
},
101+
102+
ResponseHeaders = new Dictionary<string, string>
103+
{
104+
["Content-Type"] = "application/json"
105+
}
98106
};
99107
}
100108

DebugProbe.AspNetCore/Assets/html/details.html

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ <h2>{{method}} {{path}}</h2>
9090
</div>
9191
</div>
9292

93+
9394
<div class="section-title">
9495
<h3>Request URL</h3>
9596

@@ -104,6 +105,20 @@ <h3>Request URL</h3>
104105
<pre>{{requestUrl}}</pre>
105106
</div>
106107

108+
<div class="section-title">
109+
<h3>Request Headers</h3>
110+
111+
<div class="code-badges">
112+
<span class="code-badge payload-text">
113+
HEADERS
114+
</span>
115+
</div>
116+
</div>
117+
118+
<div class="code-block">
119+
<button class="copy-btn" onclick="copyText(this)">Copy</button>
120+
<pre>{{requestHeaders}}</pre>
121+
</div>
107122

108123
<div class="section-title">
109124
<h3>Request Body</h3>
@@ -119,6 +134,20 @@ <h3>Request Body</h3>
119134
<pre>{{request}}</pre>
120135
</div>
121136

137+
<div class="section-title">
138+
<h3>Response Headers</h3>
139+
140+
<div class="code-badges">
141+
<span class="code-badge payload-text">
142+
HEADERS
143+
</span>
144+
</div>
145+
</div>
146+
147+
<div class="code-block">
148+
<button class="copy-btn" onclick="copyText(this)">Copy</button>
149+
<pre>{{responseHeaders}}</pre>
150+
</div>
122151

123152
<div class="section-title">
124153
<h3>Response Body</h3>

DebugProbe.AspNetCore/DebugProbe.AspNetCore.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@
4141
</ItemGroup>
4242

4343
<ItemGroup>
44-
<EmbeddedResource Include="Assets\**\*.html" />
45-
<EmbeddedResource Include="Assets\**\*.css" />
46-
<EmbeddedResource Include="Assets\**\*.js" />
47-
<EmbeddedResource Include="Assets\**\*.png" />
48-
<EmbeddedResource Include="Assets\**\*.ico" />
44+
<EmbeddedResource Include="Assets\**\*" />
45+
</ItemGroup>
46+
47+
<ItemGroup>
48+
<None Remove="Assets\**\*" />
4949
</ItemGroup>
5050

5151
<ItemGroup>

DebugProbe.AspNetCore/Internal/Rendering/HtmlRenderer.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ public static string RenderIndexPage(List<DebugEntry> items)
4343

4444
public static string RenderDetailsPage(DebugEntry x, DebugEnvironment e, string req, string res)
4545
{
46-
var headers = string.Join("", x.Headers.Select(h =>
47-
$"<tr><td>{Encode(h.Key)}</td><td>{Encode(h.Value)}</td></tr>"));
46+
//var headers = string.Join("", x.Reqe.Select(h =>
47+
// $"<tr><td>{Encode(h.Key)}</td><td>{Encode(h.Value)}</td></tr>"));
48+
49+
var requestHeaders = string.Join(Environment.NewLine, x.RequestHeaders.Select(h => $"{h.Key}: {h.Value}"));
50+
var responseHeaders = string.Join(Environment.NewLine, x.ResponseHeaders.Select(h => $"{h.Key}: {h.Value}"));
4851

4952
var pathWithQuery = string.IsNullOrEmpty(x.Query)
5053
? x.Path
@@ -79,13 +82,15 @@ public static string RenderDetailsPage(DebugEntry x, DebugEnvironment e, string
7982
.Replace("{{requestUrl}}", Encode(string.IsNullOrEmpty(x.RequestUrl) ? "" : x.RequestUrl))
8083
.Replace("{{requestType}}", GetPayloadType(req))
8184
.Replace("{{requestTypeClass}}", GetPayloadTypeClass(req))
85+
.Replace("{{requestHeaders}}", Encode(requestHeaders))
8286
.Replace("{{request}}", Encode(string.IsNullOrEmpty(req) ? "" : req))
8387

8488
.Replace("{{responseType}}", GetPayloadType(res))
8589
.Replace("{{responseTypeClass}}", GetPayloadTypeClass(res))
86-
.Replace("{{response}}", Encode(string.IsNullOrEmpty(res) ? "" : res))
90+
.Replace("{{responseHeaders}}", Encode(responseHeaders))
91+
.Replace("{{response}}", Encode(string.IsNullOrEmpty(res) ? "" : res));
8792

88-
.Replace("{{headers}}", headers);
93+
//.Replace("{{headers}}", headers);
8994

9095
return BuildLayout(content);
9196
}

DebugProbe.AspNetCore/Middleware/DebugProbeMiddleware.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ public async Task Invoke(HttpContext context, DebugEntryStore store)
9595
RequestSize = context.Request.ContentLength ?? Encoding.UTF8.GetByteCount(requestBody),
9696
ResponseSize = Encoding.UTF8.GetByteCount(responseBody),
9797

98+
99+
// Request Headers
100+
RequestHeaders = context.Request.Headers.ToDictionary(x => x.Key, x =>
101+
SensitiveHeaders.Contains(x.Key) ? "[REDACTED]" : x.Value.ToString()),
102+
98103
// Request
99104
RequestUrl = $"{context.Request.Scheme}://{context.Request.Host}" +
100105
$"{context.Request.Path}{context.Request.QueryString}",
@@ -103,10 +108,9 @@ public async Task Invoke(HttpContext context, DebugEntryStore store)
103108
// Response
104109
ResponseBody = Trim(responseBody, maxBodySize),
105110

106-
// Headers
107-
Headers = context.Request.Headers.ToDictionary(
108-
x => x.Key,
109-
x => SensitiveHeaders.Contains(x.Key) ? "[REDACTED]" : x.Value.ToString()),
111+
// Response Headers
112+
ResponseHeaders = context.Response.Headers.ToDictionary(x => x.Key, x =>
113+
SensitiveHeaders.Contains(x.Key)? "[REDACTED]" : x.Value.ToString()),
110114

111115
// Other
112116
Timestamp = DateTime.UtcNow,

DebugProbe.AspNetCore/Models/DebugEntry.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ public class DebugEntry
2020
public string ResponseBody { get; set; } = default!;
2121

2222
// Headers
23-
public Dictionary<string, string> Headers { get; set; } = new();
23+
public Dictionary<string, string> RequestHeaders { get; set; } = new();
24+
public Dictionary<string, string> ResponseHeaders { get; set; } = new();
2425

2526
// Metadata
2627
public DateTimeOffset Timestamp { get; set; }

0 commit comments

Comments
 (0)