update rest lib to fix recoverd panic
This commit is contained in:
Generated
+3
-3
@@ -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"
|
||||
|
||||
+3
-2
@@ -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
|
||||
|
||||
+5
@@ -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()...)
|
||||
}
|
||||
|
||||
+64
-17
@@ -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
|
||||
|
||||
+7
@@ -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) {
|
||||
|
||||
+54
@@ -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))
|
||||
}
|
||||
Reference in New Issue
Block a user