diff --git a/middleware/logger.go b/middleware/logger.go index 395b2ea5..642b46af 100644 --- a/middleware/logger.go +++ b/middleware/logger.go @@ -5,6 +5,7 @@ import ( "io" "os" "strconv" + "strings" "sync" "time" @@ -36,6 +37,9 @@ type ( // - latency_human (Human readable) // - bytes_in (Bytes received) // - bytes_out (Bytes sent) + // - header: + // - query: + // - form: // // Example "${remote_ip} ${status}" // @@ -160,6 +164,15 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc { return w.Write([]byte(b)) case "bytes_out": return w.Write([]byte(strconv.FormatInt(res.Size, 10))) + default: + switch { + case strings.HasPrefix(tag, "header:"): + return buf.Write([]byte(c.Request().Header.Get(tag[7:]))) + case strings.HasPrefix(tag, "query:"): + return buf.Write([]byte(c.QueryParam(tag[6:]))) + case strings.HasPrefix(tag, "form:"): + return buf.Write([]byte(c.FormValue(tag[5:]))) + } } return 0, nil }) diff --git a/middleware/logger_test.go b/middleware/logger_test.go index 0e7614b8..6fed41be 100644 --- a/middleware/logger_test.go +++ b/middleware/logger_test.go @@ -5,6 +5,8 @@ import ( "errors" "net/http" "net/http/httptest" + "net/url" + "strings" "testing" "github.com/labstack/echo" @@ -78,3 +80,56 @@ func TestLoggerIPAddress(t *testing.T) { h(c) assert.Contains(t, ip, buf.String()) } + +func TestLoggerTemplate(t *testing.T) { + buf := new(bytes.Buffer) + + e := echo.New() + e.Use(LoggerWithConfig(LoggerConfig{ + Format: `{"time":"${time_rfc3339}","remote_ip":"${remote_ip}","host":"${host}","user_agent":"${user_agent}",` + + `"method":"${method}","uri":"${uri}","status":${status}, "latency":${latency},` + + `"latency_human":"${latency_human}","bytes_in":${bytes_in}, "path":"${path}", "referer":"${referer}",` + + `"bytes_out":${bytes_out},"ch":"${header:X-Custom-Header}",` + + `"us":"${query:username}", "cf":"${form:username}"}` + "\n", + Output: buf, + })) + + e.GET("/", func(c echo.Context) error { + return c.String(http.StatusOK, "Header Logged") + }) + + req, _ := http.NewRequest(echo.GET, "/?username=apagano-param&password=secret", nil) + req.RequestURI = "/" + req.Header.Add(echo.HeaderXRealIP, "127.0.0.1") + req.Header.Add("Referer", "google.com") + req.Header.Add("User-Agent", "echo-tests-agent") + req.Header.Add("X-Custom-Header", "AAA-CUSTOM-VALUE") + req.Form = url.Values{ + "username": []string{"apagano-form"}, + "password": []string{"secret-form"}, + } + + rec := httptest.NewRecorder() + e.ServeHTTP(rec, req) + + cases := map[string]bool{ + "apagano-param": true, + "apagano-form": true, + "AAA-CUSTOM-VALUE": true, + "BBB-CUSTOM-VALUE": false, + "secret-form": false, + "hexvalue": false, + "GET": true, + "127.0.0.1": true, + "\"path\":\"/\"": true, + "\"uri\":\"/\"": true, + "\"status\":200": true, + "\"bytes_in\":0": true, + "google.com": true, + "echo-tests-agent": true, + } + + for token, present := range cases { + assert.True(t, strings.Contains(buf.String(), token) == present, "Case: "+token) + } +} diff --git a/website/content/middleware/logger.md b/website/content/middleware/logger.md index 33754455..844017fc 100644 --- a/website/content/middleware/logger.md +++ b/website/content/middleware/logger.md @@ -63,6 +63,9 @@ LoggerConfig struct { // - latency_human (Human readable) // - bytes_in (Bytes received) // - bytes_out (Bytes sent) + // - header: + // - query: + // - form: // // Example "${remote_ip} ${status}" //