mirror of
https://github.com/labstack/echo.git
synced 2025-01-01 22:09:21 +02:00
Merge branch 'request-id' of https://github.com/usk81/echo into usk81-request-id
This commit is contained in:
commit
66ae47cf9f
24
glide.lock
generated
24
glide.lock
generated
@ -1,10 +1,10 @@
|
||||
hash: 3de2a96bbdc145cce325de2a482111b0524cc330f60a4fbc781a08ed3b879e58
|
||||
updated: 2017-01-28T10:22:00.230111692-08:00
|
||||
hash: ffd2479be96adb7a9a21f8672a826e1e5868ab022bc7da1aa71f7b5d005ce03e
|
||||
updated: 2017-02-10T11:14:02.230514143+09:00
|
||||
imports:
|
||||
- name: github.com/daaku/go.zipexe
|
||||
version: a5fe2436ffcb3236e175e5149162b41cd28bd27d
|
||||
- name: github.com/dgrijalva/jwt-go
|
||||
version: a601269ab70c205d26370c16f7c81e9017c14e04
|
||||
version: 2268707a8f0843315e2004ee4f1d021dc08baedf
|
||||
- name: github.com/facebookgo/clock
|
||||
version: 600d898af40aa09a7a93ecb9265d87b0504b6f03
|
||||
- name: github.com/facebookgo/grace
|
||||
@ -27,7 +27,7 @@ imports:
|
||||
- name: github.com/gorilla/websocket
|
||||
version: c36f2fe5c330f0ac404b616b96c438b8616b1aaf
|
||||
- name: github.com/kardianos/osext
|
||||
version: c2c54e542fb797ad986b31721e1baedf214ca413
|
||||
version: 9b883c5eb462dd5cb1b0a7a104fe86bc6b9bd391
|
||||
- name: github.com/labstack/gommon
|
||||
version: f72d3c883f8ea180da8f085dd320804c41332ad1
|
||||
subpackages:
|
||||
@ -38,30 +38,32 @@ imports:
|
||||
- name: github.com/mattn/go-colorable
|
||||
version: d228849504861217f796da67fae4f6e347643f15
|
||||
- name: github.com/mattn/go-isatty
|
||||
version: 30a891c33c7cde7b02a981314b4228ec99380cca
|
||||
version: 281032e84ae07510239465db46bf442aa44b953a
|
||||
- name: github.com/satori/go.uuid
|
||||
version: b061729afc07e77a8aa4fad0a2fd840958f1942a
|
||||
- name: github.com/tylerb/graceful
|
||||
version: 0e9129e9c6d47da90dc0c188b26bd7bb1dab53cd
|
||||
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
|
||||
- name: github.com/valyala/bytebufferpool
|
||||
version: e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7
|
||||
- name: github.com/valyala/fasttemplate
|
||||
version: d090d65668a286d9a180d43a19dfdc5dcad8fe88
|
||||
- name: golang.org/x/crypto
|
||||
version: 9477e0b78b9ac3d0b03822fd95422e2fe07627cd
|
||||
version: 453249f01cfeb54c3d549ddb75ff152ca243f9d8
|
||||
subpackages:
|
||||
- acme
|
||||
- acme/autocert
|
||||
- name: golang.org/x/net
|
||||
version: f2499483f923065a842d38eb4c7f1927e6fc6e6d
|
||||
version: a689eb3bc4b53af70390acc3cf68c9f549b6b8d6
|
||||
subpackages:
|
||||
- context
|
||||
- context/ctxhttp
|
||||
- websocket
|
||||
- name: golang.org/x/sys
|
||||
version: d75a52659825e75fff6158388dddc6a5b04f9ba5
|
||||
version: 7a6e5648d140666db5d920909e082ca00a87ba2c
|
||||
subpackages:
|
||||
- unix
|
||||
- name: google.golang.org/appengine
|
||||
version: a2c54d2174c17540446e0ced57d9d459af61bc1c
|
||||
version: 2e4a801b39fc199db615bfca7d0b9f8cd9580599
|
||||
subpackages:
|
||||
- internal
|
||||
- internal/app_identity
|
||||
@ -87,6 +89,6 @@ testImports:
|
||||
subpackages:
|
||||
- difflib
|
||||
- name: github.com/stretchr/testify
|
||||
version: 2402e8e7a02fc811447d11f881aa9746cdc57983
|
||||
version: 4d4bfba8f1d1027c4fdbe371823030df51419987
|
||||
subpackages:
|
||||
- assert
|
||||
|
@ -12,6 +12,7 @@ import:
|
||||
- color
|
||||
- log
|
||||
- random
|
||||
- package: github.com/satori/go.uuid
|
||||
- package: github.com/tylerb/graceful
|
||||
- package: github.com/valyala/fasttemplate
|
||||
- package: golang.org/x/crypto
|
||||
|
@ -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":"${request_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",
|
||||
@ -169,6 +169,12 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
|
||||
return buf.WriteString(cl)
|
||||
case "bytes_out":
|
||||
return buf.WriteString(strconv.FormatInt(res.Size, 10))
|
||||
case "request_id":
|
||||
ri := req.Header.Get("X-Request-ID")
|
||||
if ri == "" {
|
||||
ri = res.Header().Get("X-Request-ID")
|
||||
}
|
||||
return w.Write([]byte(ri))
|
||||
default:
|
||||
switch {
|
||||
case strings.HasPrefix(tag, "header:"):
|
||||
|
@ -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":"${request_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 {
|
||||
|
51
middleware/request_id.go
Normal file
51
middleware/request_id.go
Normal file
@ -0,0 +1,51 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
type (
|
||||
// RequestIDConfig defines the config for RequestID middleware.
|
||||
RequestIDConfig struct {
|
||||
// Skipper defines a function to skip middleware.
|
||||
Skipper Skipper
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// DefaultRequestIDConfig is the default RequestID middleware config.
|
||||
DefaultRequestIDConfig = RequestIDConfig{
|
||||
Skipper: DefaultSkipper,
|
||||
}
|
||||
)
|
||||
|
||||
// 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 {
|
||||
if config.Skipper == nil {
|
||||
config.Skipper = DefaultRequestIDConfig.Skipper
|
||||
}
|
||||
|
||||
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("X-Request-ID")
|
||||
if rid == "" {
|
||||
rid = uuid.NewV4().String()
|
||||
}
|
||||
res.Header().Set("X-Request-ID", rid)
|
||||
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
30
middleware/request_id_test.go
Normal file
30
middleware/request_id_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"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)
|
||||
if assert.NotEmpty(t, rec.Header().Get("X-Request-ID")) {
|
||||
u, err := uuid.FromString(rec.Header().Get("X-Request-ID"))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, uint(4), u.Version())
|
||||
assert.Equal(t, uint(uuid.VariantRFC4122), u.Variant())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user