diff --git a/pkg/middlewares/accesslog/logger.go b/pkg/middlewares/accesslog/logger.go index cf729c6de..ed85a8888 100644 --- a/pkg/middlewares/accesslog/logger.go +++ b/pkg/middlewares/accesslog/logger.go @@ -105,15 +105,28 @@ func NewHandler(config *types.AccessLog) (*Handler, error) { Level: logrus.InfoLevel, } - // Transform headers names in config to a canonical form, to be used as is without further transformations. - if config.Fields != nil && config.Fields.Headers != nil && len(config.Fields.Headers.Names) > 0 { - fields := map[string]string{} + // Transform header names to a canonical form, to be used as is without further transformations, + // and transform field names to lower case, to enable case-insensitive lookup. + if config.Fields != nil { + if len(config.Fields.Names) > 0 { + fields := map[string]string{} - for h, v := range config.Fields.Headers.Names { - fields[textproto.CanonicalMIMEHeaderKey(h)] = v + for h, v := range config.Fields.Names { + fields[strings.ToLower(h)] = v + } + + config.Fields.Names = fields } - config.Fields.Headers.Names = fields + if config.Fields.Headers != nil && len(config.Fields.Headers.Names) > 0 { + fields := map[string]string{} + + for h, v := range config.Fields.Headers.Names { + fields[textproto.CanonicalMIMEHeaderKey(h)] = v + } + + config.Fields.Headers.Names = fields + } } logHandler := &Handler{ @@ -332,7 +345,7 @@ func (h *Handler) logTheRoundTrip(logDataTable *LogData) { fields := logrus.Fields{} for k, v := range logDataTable.Core { - if h.config.Fields.Keep(k) { + if h.config.Fields.Keep(strings.ToLower(k)) { fields[k] = v } } diff --git a/pkg/middlewares/accesslog/logger_test.go b/pkg/middlewares/accesslog/logger_test.go index 338467293..46563db61 100644 --- a/pkg/middlewares/accesslog/logger_test.go +++ b/pkg/middlewares/accesslog/logger_test.go @@ -462,6 +462,32 @@ func TestLoggerJSON(t *testing.T) { RequestRefererHeader: assertString(testReferer), }, }, + { + desc: "fields and headers with unconventional letter case", + config: &types.AccessLog{ + FilePath: "", + Format: JSONFormat, + Fields: &types.AccessLogFields{ + DefaultMode: "drop", + Names: map[string]string{ + "rEqUeStHoSt": "keep", + }, + Headers: &types.FieldHeaders{ + DefaultMode: "drop", + Names: map[string]string{ + "ReFeReR": "keep", + }, + }, + }, + }, + expected: map[string]func(t *testing.T, value interface{}){ + RequestHost: assertString(testHostname), + "level": assertString("info"), + "msg": assertString(""), + "time": assertNotEmpty(), + RequestRefererHeader: assertString(testReferer), + }, + }, } for _, test := range testCases {