Merge 387e102b37b3bb0e40cd7d741175a5bfca75e4e9 into 857db39f82fb82456af2906ccea972ae1d65ff57

This commit is contained in:
agclqq 2024-01-21 22:54:45 +07:00 committed by GitHub
commit 003ab6e835
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 3 deletions

View File

@ -5,6 +5,7 @@
package gin package gin
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -47,6 +48,10 @@ type LoggerConfig struct {
// SkipPaths is an url path array which logs are not written. // SkipPaths is an url path array which logs are not written.
// Optional. // Optional.
SkipPaths []string SkipPaths []string
// RequestBody is a bool to enable request body logging
// Optional. Default value is false
RequestBody bool
} }
// LogFormatter gives the signature of the formatter function passed to LoggerWithFormatter // LogFormatter gives the signature of the formatter function passed to LoggerWithFormatter
@ -238,11 +243,20 @@ func LoggerWithConfig(conf LoggerConfig) HandlerFunc {
path := c.Request.URL.Path path := c.Request.URL.Path
raw := c.Request.URL.RawQuery raw := c.Request.URL.RawQuery
var body []byte
if conf.RequestBody {
body, _ = io.ReadAll(c.Request.Body)
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
}
// Process request // Process request
c.Next() c.Next()
// Log only when path is not being skipped // Log only when path is not being skipped
if _, ok := skip[path]; !ok { if _, ok := skip[path]; !ok {
if conf.RequestBody {
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
}
param := LogFormatterParams{ param := LogFormatterParams{
Request: c.Request, Request: c.Request,
isTerm: isTerm, isTerm: isTerm,

View File

@ -5,8 +5,10 @@
package gin package gin
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"io"
"net/http" "net/http"
"strings" "strings"
"testing" "testing"
@ -182,18 +184,21 @@ func TestLoggerWithFormatter(t *testing.T) {
func TestLoggerWithConfigFormatting(t *testing.T) { func TestLoggerWithConfigFormatting(t *testing.T) {
var gotParam LogFormatterParams var gotParam LogFormatterParams
var gotKeys map[string]any var gotKeys map[string]any
var gotBody []byte
buffer := new(strings.Builder) buffer := new(strings.Builder)
router := New() router := New()
router.engine.trustedCIDRs, _ = router.engine.prepareTrustedCIDRs() router.engine.trustedCIDRs, _ = router.engine.prepareTrustedCIDRs()
router.Use(LoggerWithConfig(LoggerConfig{ router.Use(LoggerWithConfig(LoggerConfig{
Output: buffer, Output: buffer,
RequestBody: true,
Formatter: func(param LogFormatterParams) string { Formatter: func(param LogFormatterParams) string {
// for assert test // for assert test
gotParam = param gotParam = param
gotBody, _ = io.ReadAll(param.Request.Body)
return fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s\n%s", return fmt.Sprintf("[FORMATTER TEST] %v | %3d | %13v | %15s | %-7s %s %s\n%s",
param.TimeStamp.Format("2006/01/02 - 15:04:05"), param.TimeStamp.Format("2006/01/02 - 15:04:05"),
param.StatusCode, param.StatusCode,
param.Latency, param.Latency,
@ -201,6 +206,7 @@ func TestLoggerWithConfigFormatting(t *testing.T) {
param.Method, param.Method,
param.Path, param.Path,
param.ErrorMessage, param.ErrorMessage,
string(gotBody),
) )
}, },
})) }))
@ -229,6 +235,16 @@ func TestLoggerWithConfigFormatting(t *testing.T) {
assert.Equal(t, "/example?a=100", gotParam.Path) assert.Equal(t, "/example?a=100", gotParam.Path)
assert.Empty(t, gotParam.ErrorMessage) assert.Empty(t, gotParam.ErrorMessage)
assert.Equal(t, gotKeys, gotParam.Keys) assert.Equal(t, gotKeys, gotParam.Keys)
router.POST("/example", func(c *Context) {
// set dummy ClientIP
c.Request.Header.Set("X-Forwarded-For", "20.20.20.20")
time.Sleep(time.Millisecond)
})
PerformBodyRequest(router, "POST", "/example", []header{}, bytes.NewBufferString(`{"name":"test"}`))
// LogFormatterParams post body test
assert.Equal(t, string(gotBody), `{"name":"test"}`)
} }
func TestDefaultLogFormatter(t *testing.T) { func TestDefaultLogFormatter(t *testing.T) {

View File

@ -6,6 +6,7 @@ package gin
import ( import (
"fmt" "fmt"
"io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
@ -30,7 +31,15 @@ func PerformRequest(r http.Handler, method, path string, headers ...header) *htt
r.ServeHTTP(w, req) r.ServeHTTP(w, req)
return w return w
} }
func PerformBodyRequest(r http.Handler, method, path string, headers []header, body io.Reader) *httptest.ResponseRecorder {
req := httptest.NewRequest(method, path, body)
for _, h := range headers {
req.Header.Add(h.Key, h.Value)
}
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
func testRouteOK(method string, t *testing.T) { func testRouteOK(method string, t *testing.T) {
passed := false passed := false
passedAny := false passedAny := false