From 4917ba01ec7c84c6fa84143d47e98b0b0a579cea Mon Sep 17 00:00:00 2001 From: Umputun Date: Wed, 6 Feb 2019 00:45:47 -0600 Subject: [PATCH] update rest lib to fix recoverd panic --- backend/Gopkg.lock | 6 +- .../github.com/go-pkgz/rest/.travis.yml | 5 +- .../github.com/go-pkgz/rest/blackwords.go | 5 ++ .../github.com/go-pkgz/rest/logger/logger.go | 81 +++++++++++++++---- .../github.com/go-pkgz/rest/logger/options.go | 7 ++ .../vendor/github.com/go-pkgz/rest/trace.go | 54 +++++++++++++ 6 files changed, 136 insertions(+), 22 deletions(-) create mode 100644 backend/vendor/github.com/go-pkgz/rest/trace.go diff --git a/backend/Gopkg.lock b/backend/Gopkg.lock index 90e85ed9..f9a9ced4 100644 --- a/backend/Gopkg.lock +++ b/backend/Gopkg.lock @@ -162,7 +162,7 @@ version = "v1.1.1" [[projects]] - digest = "1:9aba5c95373481f118e57e9740d9e82f86802d86849809ab89324bcb4f236451" + digest = "1:27df73e1f59fffb9aaa2c28ba81561f177710576f18ad602564949355fac3e23" name = "github.com/go-pkgz/rest" packages = [ ".", @@ -170,8 +170,8 @@ "logger", ] pruneopts = "UT" - revision = "e7d08d0194d613b8854de2e487bf7732500fa153" - version = "v1.2.0" + revision = "27af5e3ba9439ec0df51c30794f473befe0a0e6d" + version = "v1.3.1" [[projects]] digest = "1:92b44856ee15e8a98b91d751a60b512017e0ba227d1ed9d2c02ad13d67062ff8" diff --git a/backend/vendor/github.com/go-pkgz/rest/.travis.yml b/backend/vendor/github.com/go-pkgz/rest/.travis.yml index 2c7beae4..f9f6de46 100644 --- a/backend/vendor/github.com/go-pkgz/rest/.travis.yml +++ b/backend/vendor/github.com/go-pkgz/rest/.travis.yml @@ -7,13 +7,14 @@ install: true before_install: - export TZ=America/Chicago - - curl -L https://git.io/vp6lP | sh + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.13.2 - go get github.com/mattn/goveralls - export PATH=$(pwd)/bin:$PATH + script: - GO111MODULE=on go get ./... - GO111MODULE=on go mod vendor - GO111MODULE=on go test -v -mod=vendor -covermode=count -coverprofile=profile.cov ./... || travis_terminate 1 - - ./bin/gometalinter --deadline=120s --exclude=test --exclude=mock --exclude=vendor --exclude=_example --disable-all --enable=errcheck --enable=vet --enable=vetshadow --enable=megacheck --enable=ineffassign --enable=varcheck --enable=unconvert --enable=deadcode --enable=interfacer --enable=gotype ./... || travis_terminate 1; + - golangci-lint run || travis_terminate 1; - $GOPATH/bin/goveralls -coverprofile=profile.cov -service=travis-ci diff --git a/backend/vendor/github.com/go-pkgz/rest/blackwords.go b/backend/vendor/github.com/go-pkgz/rest/blackwords.go index 65e764a7..62afe8e3 100644 --- a/backend/vendor/github.com/go-pkgz/rest/blackwords.go +++ b/backend/vendor/github.com/go-pkgz/rest/blackwords.go @@ -32,3 +32,8 @@ func BlackWords(words ...string) func(http.Handler) http.Handler { return http.HandlerFunc(fn) } } + +// BlackWordsFn middleware uses func to get the list and doesn't allow some words in the request body +func BlackWordsFn(fn func() []string) func(http.Handler) http.Handler { + return BlackWords(fn()...) +} diff --git a/backend/vendor/github.com/go-pkgz/rest/logger/logger.go b/backend/vendor/github.com/go-pkgz/rest/logger/logger.go index bddbad0c..3a9c7bd6 100644 --- a/backend/vendor/github.com/go-pkgz/rest/logger/logger.go +++ b/backend/vendor/github.com/go-pkgz/rest/logger/logger.go @@ -10,6 +10,7 @@ import ( "net/http" "net/url" "regexp" + "sort" "strings" "time" ) @@ -23,6 +24,7 @@ type Middleware struct { flags []Flag ipFn func(ip string) string userFn func(r *http.Request) (string, error) + subjFn func(r *http.Request) (string, error) log Backend } @@ -99,8 +101,37 @@ func (l *Middleware) Handler(next http.Handler) http.Handler { remoteIP = l.ipFn(remoteIP) } - l.log.Logf("%s %s - %s - %s - %d (%d) - %v %s %s", - l.prefix, r.Method, q, remoteIP, ww.status, ww.size, t2.Sub(t1), user, body) + var bld strings.Builder + if l.prefix != "" { + bld.WriteString(l.prefix) + bld.WriteString(" ") + } + + bld.WriteString(fmt.Sprintf("%s - %s - %s - %d (%d) - %v", r.Method, q, remoteIP, ww.status, ww.size, t2.Sub(t1))) + + if user != "" { + bld.WriteString(" - ") + bld.WriteString(user) + } + + if l.subjFn != nil { + if subj, err := l.subjFn(r); err == nil { + bld.WriteString(" - ") + bld.WriteString(subj) + } + } + + if traceID := r.Header.Get("X-Request-ID"); traceID != "" { + bld.WriteString(" - ") + bld.WriteString(traceID) + } + + if body != "" { + bld.WriteString(" - ") + bld.WriteString(body) + } + + l.log.Logf("%s", bld.String()) }() next.ServeHTTP(ww, r) @@ -133,7 +164,7 @@ func (l *Middleware) getBodyAndUser(r *http.Request) (body string, user string) if l.inLogFlags(User) && l.userFn != nil { u, err := l.userFn(r) if err == nil && u != "" { - user = fmt.Sprintf(" - %s", u) + user = u } } @@ -149,24 +180,40 @@ func (l *Middleware) inLogFlags(f Flag) bool { return false } +var hideWords = []string{"password", "passwd", "secret", "credentials", "token"} + +// hide query values for hideWords. May change order of query params func (l *Middleware) sanitizeQuery(inp string) string { - out := []rune(inp) - hide := []string{"password", "passwd", "secret", "credentials"} - for _, h := range hide { - if strings.Contains(strings.ToLower(inp), h+"=") { - stPos := strings.Index(strings.ToLower(inp), h+"=") + len(h) + 1 - fnPos := strings.Index(inp[stPos:], "&") - if fnPos == -1 { - fnPos = len(inp) - } else { - fnPos = stPos + fnPos - } - for i := stPos; i < fnPos; i++ { - out[i] = rune('*') + + inHiddenWords := func(str string) bool { + for _, w := range hideWords { + if strings.EqualFold(w, str) { + return true } } + return false } - return string(out) + + parts := strings.SplitN(inp, "?", 2) + if len(parts) < 2 { + return inp + } + + q, e := url.ParseQuery(parts[1]) + if e != nil || len(q) == 0 { + return inp + } + + res := []string{} + for k, v := range q { + if inHiddenWords(k) { + res = append(res, fmt.Sprintf("%s=********", k)) + } else { + res = append(res, fmt.Sprintf("%s=%v", k, v[0])) + } + } + sort.Strings(res) // to make testing persistent + return parts[0] + "?" + strings.Join(res, "&") } // customResponseWriter implements ResponseWriter and keeping status and size diff --git a/backend/vendor/github.com/go-pkgz/rest/logger/options.go b/backend/vendor/github.com/go-pkgz/rest/logger/options.go index 45711a30..57f6e0d1 100644 --- a/backend/vendor/github.com/go-pkgz/rest/logger/options.go +++ b/backend/vendor/github.com/go-pkgz/rest/logger/options.go @@ -44,6 +44,13 @@ func UserFn(userFn func(r *http.Request) (string, error)) Option { } } +// SubjFn functional option defines subject function. +func SubjFn(userFn func(r *http.Request) (string, error)) Option { + return func(l *Middleware) { + l.subjFn = userFn + } +} + // Log functional option defines loging backend. func Log(log Backend) Option { return func(l *Middleware) { diff --git a/backend/vendor/github.com/go-pkgz/rest/trace.go b/backend/vendor/github.com/go-pkgz/rest/trace.go new file mode 100644 index 00000000..d9701450 --- /dev/null +++ b/backend/vendor/github.com/go-pkgz/rest/trace.go @@ -0,0 +1,54 @@ +package rest + +import ( + "context" + "crypto/rand" + "crypto/sha1" + "fmt" + "net/http" + "time" +) + +type contextKey string + +const traceHeader = "X-Request-ID" + +// Trace looks for header X-Request-ID and makes it as random id if not found, then populates it to the result's header +// and to request context +func Trace(next http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + traceID := r.Header.Get(traceHeader) + if traceID == "" { + traceID = randToken() + } + w.Header().Set(traceHeader, traceID) + ctx := context.WithValue(r.Context(), contextKey("requestID"), traceID) + r = r.WithContext(ctx) + next.ServeHTTP(w, r) + } + return http.HandlerFunc(fn) +} + +// GetTraceID returns request id from the context +func GetTraceID(r *http.Request) string { + if id, ok := r.Context().Value(contextKey("requestID")).(string); ok { + return id + } + return "" +} + +func randToken() string { + fallback := func() string { + return fmt.Sprintf("%x", time.Now().Nanosecond()) + } + + b := make([]byte, 32) + if _, err := rand.Read(b); err != nil { + return fallback() + } + s := sha1.New() + if _, err := s.Write(b); err != nil { + return fallback() + } + return fmt.Sprintf("%x", s.Sum(nil)) +}