Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add case-insensitive fallback for response header logging #150

Merged
merged 5 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
997 changes: 500 additions & 497 deletions .paket/Paket.Restore.targets

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions examples/github/GitHub.fsproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>IIS Express</ActiveDebugProfile>
</PropertyGroup>
</Project>
6 changes: 6 additions & 0 deletions examples/wikisearch/WikiSearch.fsproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>IIS Express</ActiveDebugProfile>
</PropertyGroup>
</Project>
16 changes: 10 additions & 6 deletions src/Logging.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,23 @@ module Logging =
let private replacer (_: Match) : string =
$"{{{PlaceHolder.ResponseHeader}__{Interlocked.Increment(&placeholderCounter)}}}"

let private lowerCaseHeaders (headers: Map<string, seq<string>>) : Map<string, seq<string>> =
headers |> Seq.map (fun kv -> kv.Key.ToLowerInvariant(), kv.Value) |> Map.ofSeq

let private getHeaderValue (headers: Map<string, seq<string>>) (key: string) : string =
match headers.TryGetValue(key) with
| true, v ->
match Seq.tryHead v with
| first -> if first.IsSome then first.Value else String.Empty
| false, _ -> String.Empty
headers
|> Map.tryFind key
|> Option.defaultValue Seq.empty
|> Seq.tryHead
|> Option.defaultValue String.Empty

let private log' logLevel ctx content =
match ctx.Request.Logger with
| Some logger ->
let format = ctx.Request.LogFormat
let request = ctx.Request
let matches = reqex.Matches format
let lowerCaseHeaders = lazy (lowerCaseHeaders ctx.Response.Headers)

// Create an array with values in the same order as in the format string. Important to be lazy and not
// stringify any values here. Only pass references to the objects themselves so the logger can stringify
Expand All @@ -56,7 +60,7 @@ module Logging =
| PlaceHolder.ResponseHeader ->
// GroupCollection returns empty string values for indexes beyond what was captured, therefore
// we don't cause an exception here if the optional second group was not captured
getHeaderValue ctx.Response.Headers match'.Groups[3].Value :> _
getHeaderValue lowerCaseHeaders.Value (match'.Groups[3].Value.ToLowerInvariant()) :> _
| key ->
// Look for the key in the extra info. This also enables custom HTTP handlers to add custom
// placeholders to the format string.
Expand Down
18 changes: 16 additions & 2 deletions test/Fetch.fs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ let ``Get with logging is OK`` () =
"Message"
"ResponseHeader[missing-key]"
"ResponseHeader[X-Request-ID]"
"ResponseHeader[x-request-id]"
"ResponseHeader"
"ResponseHeader["
"ResponseHeader]"
Expand Down Expand Up @@ -163,7 +164,13 @@ let ``Get with logging is OK`` () =
// Assert
test <@ logger.Output.Contains "42" @>
test <@ logger.Output.Contains "http://test.org" @>
test <@ logger.Output.Contains $"test-value\n← {msg}\n← \n← test-request-id\n← \n← \n← \n← \n← end" @>

test
<@
logger.Output.Contains
$"test-value\n← {msg}\n← \n← test-request-id\n← test-request-id\n← \n← \n← \n← \n← end"
@>

test <@ logger.Output.Contains "not-included-in-log" = false @>
test <@ Result.isOk result @>
test <@ metrics.Retries = 0L @>
Expand Down Expand Up @@ -204,6 +211,7 @@ let ``Post with logging is OK`` () =
"Message"
"ResponseHeader[missing-key]"
"ResponseHeader[X-Request-ID]"
"ResponseHeader[x-request-id]"
"ResponseHeader"
"ResponseHeader["
"ResponseHeader]"
Expand All @@ -230,7 +238,13 @@ let ``Post with logging is OK`` () =
test <@ logger.Output.Contains json @>
test <@ logger.Output.Contains msg @>
test <@ logger.Output.Contains "http://testing.org" @>
test <@ logger.Output.Contains $"test-value\n← {msg}\n← \n← test-request-id\n← \n← \n← \n← \n← end" @>

test
<@
logger.Output.Contains
$"test-value\n← {msg}\n← \n← test-request-id\n← test-request-id\n← \n← \n← \n← \n← end"
@>

test <@ logger.Output.Contains "not-included-in-log" = false @>
test <@ Result.isOk result @>
test <@ retries' = 1 @>
Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.0.1
6.0.2