mirror of
https://github.com/amir20/dozzle.git
synced 2026-08-07 09:54:45 +00:00
fix: unescape quoted logfmt values (#4844)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@ package container
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||
)
|
||||
@@ -36,7 +38,7 @@ func ParseLogFmt(log string) (*orderedmap.OrderedMap[string, string], error) {
|
||||
} else if char == '\\' {
|
||||
escaping = true
|
||||
} else if char == '"' {
|
||||
value = log[start:i]
|
||||
value = unescapeQuoted(log[start-1 : i+1])
|
||||
result.Set(key, value)
|
||||
inQuotes = false
|
||||
isKey = true
|
||||
@@ -77,3 +79,19 @@ func ParseLogFmt(log string) (*orderedmap.OrderedMap[string, string], error) {
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// unescapeQuoted decodes a quoted logfmt value (including the surrounding
|
||||
// quotes) so escape sequences like \" and \\ produced by logfmt encoders
|
||||
// (logrus, go-kit, go-logfmt) yield the original text instead of leaking
|
||||
// backslashes into the parsed value. If the sequence is not decodable, the
|
||||
// raw content between the quotes is returned unchanged.
|
||||
func unescapeQuoted(quoted string) string {
|
||||
raw := quoted[1 : len(quoted)-1]
|
||||
if !strings.ContainsRune(raw, '\\') {
|
||||
return raw
|
||||
}
|
||||
if unquoted, err := strconv.Unquote(quoted); err == nil {
|
||||
return unquoted
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
@@ -67,6 +67,28 @@ func TestParseLog(t *testing.T) {
|
||||
),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Escaped quotes and backslashes in quoted values",
|
||||
log: `level=info msg="failed to open \"config.yml\"" path="C:\\temp"`,
|
||||
want: orderedmap.New[string, string](
|
||||
orderedmap.WithInitialData(
|
||||
orderedmap.Pair[string, string]{Key: "level", Value: "info"},
|
||||
orderedmap.Pair[string, string]{Key: "msg", Value: `failed to open "config.yml"`},
|
||||
orderedmap.Pair[string, string]{Key: "path", Value: `C:\temp`},
|
||||
),
|
||||
),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Quoted value with undecodable escape is kept as-is",
|
||||
log: `msg="foo \q bar"`,
|
||||
want: orderedmap.New[string, string](
|
||||
orderedmap.WithInitialData(
|
||||
orderedmap.Pair[string, string]{Key: "msg", Value: `foo \q bar`},
|
||||
),
|
||||
),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Broken format with unexpected quotes",
|
||||
log: `key1=value"1"= key2="value2"`,
|
||||
|
||||
Reference in New Issue
Block a user