1
0
mirror of https://github.com/containous/traefik.git synced 2024-12-23 17:34:13 +03:00

fix: access logs header names filtering is case insensitive

This commit is contained in:
Mickael Jeanroy 2020-07-16 17:36:04 +02:00 committed by GitHub
parent fae2d93525
commit 45f52ca29c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 115 additions and 9 deletions

View File

@ -16,9 +16,10 @@ It has these top-level messages:
package helloworld package helloworld
import ( import (
proto "github.com/golang/protobuf/proto"
fmt "fmt" fmt "fmt"
math "math" math "math"
proto "github.com/golang/protobuf/proto"
) )
import ( import (

View File

@ -6,6 +6,7 @@ import (
"io" "io"
"net" "net"
"net/http" "net/http"
"net/textproto"
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
@ -100,6 +101,17 @@ func NewHandler(config *types.AccessLog) (*Handler, error) {
Level: logrus.InfoLevel, 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{}
for h, v := range config.Fields.Headers.Names {
fields[textproto.CanonicalMIMEHeaderKey(h)] = v
}
config.Fields.Headers.Names = fields
}
logHandler := &Handler{ logHandler := &Handler{
config: config, config: config,
logger: logger, logger: logger,

View File

@ -41,11 +41,7 @@ var (
) )
func TestLogRotation(t *testing.T) { func TestLogRotation(t *testing.T) {
tempDir, err := ioutil.TempDir("", "traefik_") tempDir := createTempDir(t, "traefik_")
if err != nil {
t.Fatalf("Error setting up temporary directory: %s", err)
}
defer os.RemoveAll(tempDir)
fileName := filepath.Join(tempDir, "traefik.log") fileName := filepath.Join(tempDir, "traefik.log")
rotatedFileName := fileName + ".rotated" rotatedFileName := fileName + ".rotated"
@ -119,9 +115,106 @@ func lineCount(t *testing.T, fileName string) int {
return count return count
} }
func TestLoggerHeaderFields(t *testing.T) {
tmpDir := createTempDir(t, CommonFormat)
expectedValue := "expectedValue"
testCases := []struct {
desc string
accessLogFields types.AccessLogFields
header string
expected string
}{
{
desc: "with default mode",
header: "User-Agent",
expected: types.AccessLogDrop,
accessLogFields: types.AccessLogFields{
DefaultMode: types.AccessLogDrop,
Headers: &types.FieldHeaders{
DefaultMode: types.AccessLogDrop,
Names: map[string]string{},
},
},
},
{
desc: "with exact header name",
header: "User-Agent",
expected: types.AccessLogKeep,
accessLogFields: types.AccessLogFields{
DefaultMode: types.AccessLogDrop,
Headers: &types.FieldHeaders{
DefaultMode: types.AccessLogDrop,
Names: map[string]string{
"User-Agent": types.AccessLogKeep,
},
},
},
},
{
desc: "with case insensitive match on header name",
header: "User-Agent",
expected: types.AccessLogKeep,
accessLogFields: types.AccessLogFields{
DefaultMode: types.AccessLogDrop,
Headers: &types.FieldHeaders{
DefaultMode: types.AccessLogDrop,
Names: map[string]string{
"user-agent": types.AccessLogKeep,
},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
logFile, err := ioutil.TempFile(tmpDir, "*.log")
require.NoError(t, err)
config := &types.AccessLog{
FilePath: logFile.Name(),
Format: CommonFormat,
Fields: &test.accessLogFields,
}
logger, err := NewHandler(config)
require.NoError(t, err)
defer logger.Close()
if config.FilePath != "" {
_, err = os.Stat(config.FilePath)
require.NoError(t, err, fmt.Sprintf("logger should create %s", config.FilePath))
}
req := &http.Request{
Header: map[string][]string{},
URL: &url.URL{
Path: testPath,
},
}
req.Header.Set(test.header, expectedValue)
logger.ServeHTTP(httptest.NewRecorder(), req, http.HandlerFunc(func(writer http.ResponseWriter, r *http.Request) {
writer.WriteHeader(http.StatusOK)
}))
logData, err := ioutil.ReadFile(logFile.Name())
require.NoError(t, err)
if test.expected == types.AccessLogDrop {
assert.NotContains(t, string(logData), expectedValue)
} else {
assert.Contains(t, string(logData), expectedValue)
}
})
}
}
func TestLoggerCLF(t *testing.T) { func TestLoggerCLF(t *testing.T) {
tmpDir := createTempDir(t, CommonFormat) tmpDir := createTempDir(t, CommonFormat)
defer os.RemoveAll(tmpDir)
logFilePath := filepath.Join(tmpDir, logFileNameSuffix) logFilePath := filepath.Join(tmpDir, logFileNameSuffix)
config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat} config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat}
@ -136,7 +229,6 @@ func TestLoggerCLF(t *testing.T) {
func TestAsyncLoggerCLF(t *testing.T) { func TestAsyncLoggerCLF(t *testing.T) {
tmpDir := createTempDir(t, CommonFormat) tmpDir := createTempDir(t, CommonFormat)
defer os.RemoveAll(tmpDir)
logFilePath := filepath.Join(tmpDir, logFileNameSuffix) logFilePath := filepath.Join(tmpDir, logFileNameSuffix)
config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat, BufferingSize: 1024} config := &types.AccessLog{FilePath: logFilePath, Format: CommonFormat, BufferingSize: 1024}
@ -358,7 +450,6 @@ func TestLoggerJSON(t *testing.T) {
t.Parallel() t.Parallel()
tmpDir := createTempDir(t, JSONFormat) tmpDir := createTempDir(t, JSONFormat)
defer os.RemoveAll(tmpDir)
logFilePath := filepath.Join(tmpDir, logFileNameSuffix) logFilePath := filepath.Join(tmpDir, logFileNameSuffix)
@ -642,6 +733,8 @@ func createTempDir(t *testing.T, prefix string) string {
tmpDir, err := ioutil.TempDir("", prefix) tmpDir, err := ioutil.TempDir("", prefix)
require.NoError(t, err, "failed to create temp dir") require.NoError(t, err, "failed to create temp dir")
t.Cleanup(func() { _ = os.RemoveAll(tmpDir) })
return tmpDir return tmpDir
} }