1
0
mirror of https://github.com/labstack/echo.git synced 2024-11-28 08:38:39 +02:00

Merge branch 'usk81-request-id'

This commit is contained in:
Vishal Rana 2017-03-06 13:17:56 -08:00
commit d011ca6c83
6 changed files with 114 additions and 18 deletions

View File

@ -183,6 +183,7 @@ const (
HeaderXHTTPMethodOverride = "X-HTTP-Method-Override"
HeaderXForwardedFor = "X-Forwarded-For"
HeaderXRealIP = "X-Real-IP"
HeaderXRequestID = "X-Request-ID"
HeaderServer = "Server"
HeaderOrigin = "Origin"
HeaderAccessControlRequestMethod = "Access-Control-Request-Method"

View File

@ -26,7 +26,7 @@ type (
// - time_unix_nano
// - time_rfc3339
// - time_rfc3339_nano
// - id (Request ID - Not implemented)
// - id (Request ID)
// - remote_ip
// - uri
// - host
@ -62,7 +62,7 @@ var (
// DefaultLoggerConfig is the default Logger middleware config.
DefaultLoggerConfig = LoggerConfig{
Skipper: DefaultSkipper,
Format: `{"time":"${time_rfc3339_nano}","remote_ip":"${remote_ip}","host":"${host}",` +
Format: `{"time":"${time_rfc3339_nano}","id":"${id}","remote_ip":"${remote_ip}","host":"${host}",` +
`"method":"${method}","uri":"${uri}","status":${status}, "latency":${latency},` +
`"latency_human":"${latency_human}","bytes_in":${bytes_in},` +
`"bytes_out":${bytes_out}}` + "\n",
@ -126,6 +126,12 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
return buf.WriteString(time.Now().Format(time.RFC3339))
case "time_rfc3339_nano":
return buf.WriteString(time.Now().Format(time.RFC3339Nano))
case "id":
id := req.Header.Get(echo.HeaderXRequestID)
if id == "" {
id = res.Header().Get(echo.HeaderXRequestID)
}
return buf.WriteString(id)
case "remote_ip":
return buf.WriteString(c.RealIP())
case "host":

View File

@ -86,7 +86,7 @@ func TestLoggerTemplate(t *testing.T) {
e := echo.New()
e.Use(LoggerWithConfig(LoggerConfig{
Format: `{"time":"${time_rfc3339_nano}","remote_ip":"${remote_ip}","host":"${host}","user_agent":"${user_agent}",` +
Format: `{"time":"${time_rfc3339_nano}","id":"${id}","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}",` +
@ -104,6 +104,7 @@ func TestLoggerTemplate(t *testing.T) {
req.Header.Add("Referer", "google.com")
req.Header.Add("User-Agent", "echo-tests-agent")
req.Header.Add("X-Custom-Header", "AAA-CUSTOM-VALUE")
req.Header.Add("X-Request-ID", "6ba7b810-9dad-11d1-80b4-00c04fd430c8")
req.Form = url.Values{
"username": []string{"apagano-form"},
"password": []string{"secret-form"},
@ -113,20 +114,21 @@ func TestLoggerTemplate(t *testing.T) {
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,
"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,
"6ba7b810-9dad-11d1-80b4-00c04fd430c8": true,
}
for token, present := range cases {

64
middleware/request_id.go Normal file
View File

@ -0,0 +1,64 @@
package middleware
import (
"github.com/labstack/echo"
"github.com/labstack/gommon/random"
)
type (
// RequestIDConfig defines the config for RequestID middleware.
RequestIDConfig struct {
// Skipper defines a function to skip middleware.
Skipper Skipper
// Generator defines a function to generate an ID.
// Optional. Default value random.String(32).
Generator func() string
}
)
var (
// DefaultRequestIDConfig is the default RequestID middleware config.
DefaultRequestIDConfig = RequestIDConfig{
Skipper: DefaultSkipper,
Generator: generator,
}
)
// RequestID returns a X-Request-ID middleware.
func RequestID() echo.MiddlewareFunc {
return RequestIDWithConfig(DefaultRequestIDConfig)
}
// RequestIDWithConfig returns a X-Request-ID middleware with config.
func RequestIDWithConfig(config RequestIDConfig) echo.MiddlewareFunc {
// Defaults
if config.Skipper == nil {
config.Skipper = DefaultRequestIDConfig.Skipper
}
if config.Generator == nil {
config.Generator = generator
}
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if config.Skipper(c) {
return next(c)
}
req := c.Request()
res := c.Response()
rid := req.Header.Get(echo.HeaderXRequestID)
if rid == "" {
rid = random.String(32)
}
res.Header().Set(echo.HeaderXRequestID, rid)
return next(c)
}
}
}
func generator() string {
return random.String(32)
}

View File

@ -0,0 +1,23 @@
package middleware
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/labstack/echo"
"github.com/stretchr/testify/assert"
)
func TestRequestID(t *testing.T) {
e := echo.New()
req, _ := http.NewRequest(echo.GET, "/", nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
rid := RequestIDWithConfig(RequestIDConfig{})
h := rid(func(c echo.Context) error {
return c.String(http.StatusOK, "test")
})
h(c)
assert.Len(t, rec.Header().Get(echo.HeaderXRequestID), 32)
}

View File

@ -51,7 +51,7 @@ LoggerConfig struct {
// - time_unix_nano
// - time_rfc3339
// - time_rfc3339_nano
// - id (Request ID - Not implemented)
// - id (Request ID)
// - remote_ip
// - uri
// - host