diff options
Diffstat (limited to 'vendor/github.com/labstack/echo/v4')
20 files changed, 359 insertions, 111 deletions
diff --git a/vendor/github.com/labstack/echo/v4/.travis.yml b/vendor/github.com/labstack/echo/v4/.travis.yml index 30346d7f..3897356d 100644 --- a/vendor/github.com/labstack/echo/v4/.travis.yml +++ b/vendor/github.com/labstack/echo/v4/.travis.yml @@ -1,6 +1,7 @@ language: go go: - 1.11.x + - 1.12.x - tip env: - GO111MODULE=on diff --git a/vendor/github.com/labstack/echo/v4/README.md b/vendor/github.com/labstack/echo/v4/README.md index 1db5e356..0da03122 100644 --- a/vendor/github.com/labstack/echo/v4/README.md +++ b/vendor/github.com/labstack/echo/v4/README.md @@ -56,30 +56,29 @@ Lower is better! package main import ( - "net/http" - - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" + "net/http" + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" ) func main() { - // Echo instance - e := echo.New() + // Echo instance + e := echo.New() - // Middleware - e.Use(middleware.Logger()) - e.Use(middleware.Recover()) + // Middleware + e.Use(middleware.Logger()) + e.Use(middleware.Recover()) - // Routes - e.GET("/", hello) + // Routes + e.GET("/", hello) - // Start server - e.Logger.Fatal(e.Start(":1323")) + // Start server + e.Logger.Fatal(e.Start(":1323")) } // Handler func hello(c echo.Context) error { - return c.String(http.StatusOK, "Hello, World!") + return c.String(http.StatusOK, "Hello, World!") } ``` diff --git a/vendor/github.com/labstack/echo/v4/bind.go b/vendor/github.com/labstack/echo/v4/bind.go index cb65ed2d..07d8034c 100644 --- a/vendor/github.com/labstack/echo/v4/bind.go +++ b/vendor/github.com/labstack/echo/v4/bind.go @@ -1,6 +1,7 @@ package echo import ( + "encoding" "encoding/json" "encoding/xml" "errors" @@ -21,6 +22,8 @@ type ( DefaultBinder struct{} // BindUnmarshaler is the interface used to wrap the UnmarshalParam method. + // Types that don't implement this, but do implement encoding.TextUnmarshaler + // will use that interface instead. BindUnmarshaler interface { // UnmarshalParam decodes and assigns a value from an form or query param. UnmarshalParam(param string) error @@ -211,12 +214,30 @@ func bindUnmarshaler(field reflect.Value) (BindUnmarshaler, bool) { return nil, false } +// textUnmarshaler attempts to unmarshal a reflect.Value into a TextUnmarshaler +func textUnmarshaler(field reflect.Value) (encoding.TextUnmarshaler, bool) { + ptr := reflect.New(field.Type()) + if ptr.CanInterface() { + iface := ptr.Interface() + if unmarshaler, ok := iface.(encoding.TextUnmarshaler); ok { + return unmarshaler, ok + } + } + return nil, false +} + func unmarshalFieldNonPtr(value string, field reflect.Value) (bool, error) { if unmarshaler, ok := bindUnmarshaler(field); ok { err := unmarshaler.UnmarshalParam(value) field.Set(reflect.ValueOf(unmarshaler).Elem()) return true, err } + if unmarshaler, ok := textUnmarshaler(field); ok { + err := unmarshaler.UnmarshalText([]byte(value)) + field.Set(reflect.ValueOf(unmarshaler).Elem()) + return true, err + } + return false, nil } diff --git a/vendor/github.com/labstack/echo/v4/context.go b/vendor/github.com/labstack/echo/v4/context.go index d4722700..065f5815 100644 --- a/vendor/github.com/labstack/echo/v4/context.go +++ b/vendor/github.com/labstack/echo/v4/context.go @@ -13,6 +13,7 @@ import ( "os" "path/filepath" "strings" + "sync" ) type ( @@ -198,6 +199,7 @@ type ( handler HandlerFunc store Map echo *Echo + lock sync.RWMutex } ) @@ -232,7 +234,7 @@ func (c *context) IsTLS() bool { func (c *context) IsWebSocket() bool { upgrade := c.request.Header.Get(HeaderUpgrade) - return upgrade == "websocket" || upgrade == "Websocket" + return strings.ToLower(upgrade) == "websocket" } func (c *context) Scheme() string { @@ -360,10 +362,15 @@ func (c *context) Cookies() []*http.Cookie { } func (c *context) Get(key string) interface{} { + c.lock.RLock() + defer c.lock.RUnlock() return c.store[key] } func (c *context) Set(key string, val interface{}) { + c.lock.Lock() + defer c.lock.Unlock() + if c.store == nil { c.store = make(Map) } @@ -430,7 +437,7 @@ func (c *context) json(code int, i interface{}, indent string) error { enc.SetIndent("", indent) } c.writeContentType(MIMEApplicationJSONCharsetUTF8) - c.response.WriteHeader(code) + c.response.Status = code return enc.Encode(i) } @@ -597,4 +604,3 @@ func (c *context) Reset(r *http.Request, w http.ResponseWriter) { // NOTE: Don't reset because it has to have length c.echo.maxParam at all times // c.pvalues = nil } - diff --git a/vendor/github.com/labstack/echo/v4/echo.go b/vendor/github.com/labstack/echo/v4/echo.go index 0fe6880f..56b2cf8c 100644 --- a/vendor/github.com/labstack/echo/v4/echo.go +++ b/vendor/github.com/labstack/echo/v4/echo.go @@ -43,6 +43,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" stdLog "log" "net" "net/http" @@ -56,18 +57,21 @@ import ( "github.com/labstack/gommon/color" "github.com/labstack/gommon/log" + "golang.org/x/crypto/acme" "golang.org/x/crypto/acme/autocert" ) type ( // Echo is the top-level framework instance. Echo struct { + common StdLogger *stdLog.Logger colorer *color.Color premiddleware []MiddlewareFunc middleware []MiddlewareFunc maxParam *int router *Router + routers map[string]*Router notFoundHandler HandlerFunc pool sync.Pool Server *http.Server @@ -122,10 +126,8 @@ type ( // Map defines a generic map of type `map[string]interface{}`. Map map[string]interface{} - // i is the interface for Echo and Group. - i interface { - GET(string, HandlerFunc, ...MiddlewareFunc) *Route - } + // Common struct for Echo & Group. + common struct{} ) // HTTP methods @@ -168,6 +170,8 @@ const ( charsetUTF8 = "charset=UTF-8" // PROPFIND Method can be used on collection and property resources. PROPFIND = "PROPFIND" + // REPORT Method can be used to get information about a resource, see rfc 3253 + REPORT = "REPORT" ) // Headers @@ -211,17 +215,18 @@ const ( HeaderAccessControlMaxAge = "Access-Control-Max-Age" // Security - HeaderStrictTransportSecurity = "Strict-Transport-Security" - HeaderXContentTypeOptions = "X-Content-Type-Options" - HeaderXXSSProtection = "X-XSS-Protection" - HeaderXFrameOptions = "X-Frame-Options" - HeaderContentSecurityPolicy = "Content-Security-Policy" - HeaderXCSRFToken = "X-CSRF-Token" + HeaderStrictTransportSecurity = "Strict-Transport-Security" + HeaderXContentTypeOptions = "X-Content-Type-Options" + HeaderXXSSProtection = "X-XSS-Protection" + HeaderXFrameOptions = "X-Frame-Options" + HeaderContentSecurityPolicy = "Content-Security-Policy" + HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only" + HeaderXCSRFToken = "X-CSRF-Token" ) const ( // Version of Echo - Version = "4.0.0" + Version = "4.1.5" website = "https://echo.labstack.com" // http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo banner = ` @@ -248,6 +253,7 @@ var ( PROPFIND, http.MethodPut, http.MethodTrace, + REPORT, } ) @@ -269,6 +275,7 @@ var ( ErrRendererNotRegistered = errors.New("renderer not registered") ErrInvalidRedirectCode = errors.New("invalid redirect status code") ErrCookieNotFound = errors.New("cookie not found") + ErrInvalidCertOrKeyType = errors.New("invalid cert or key type, must be string or []byte") ) // Error handlers @@ -304,6 +311,7 @@ func New() (e *Echo) { return e.NewContext(nil, nil) } e.router = NewRouter(e) + e.routers = map[string]*Router{} return } @@ -319,11 +327,16 @@ func (e *Echo) NewContext(r *http.Request, w http.ResponseWriter) Context { } } -// Router returns router. +// Router returns the default router. func (e *Echo) Router() *Router { return e.router } +// Routers returns the map of host => router. +func (e *Echo) Routers() map[string]*Router { + return e.routers +} + // DefaultHTTPErrorHandler is the default HTTP error handler. It sends a JSON response // with status code. func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) { @@ -450,10 +463,10 @@ func (e *Echo) Static(prefix, root string) *Route { if root == "" { root = "." // For security we want to restrict to CWD. } - return static(e, prefix, root) + return e.static(prefix, root, e.GET) } -func static(i i, prefix, root string) *Route { +func (common) static(prefix, root string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route) *Route { h := func(c Context) error { p, err := url.PathUnescape(c.Param("*")) if err != nil { @@ -462,26 +475,28 @@ func static(i i, prefix, root string) *Route { name := filepath.Join(root, path.Clean("/"+p)) // "/"+ for security return c.File(name) } - i.GET(prefix, h) if prefix == "/" { - return i.GET(prefix+"*", h) + return get(prefix+"*", h) } + return get(prefix+"/*", h) +} - return i.GET(prefix+"/*", h) +func (common) file(path, file string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route, + m ...MiddlewareFunc) *Route { + return get(path, func(c Context) error { + return c.File(file) + }, m...) } // File registers a new route with path to serve a static file with optional route-level middleware. func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route { - return e.GET(path, func(c Context) error { - return c.File(file) - }, m...) + return e.file(path, file, e.GET, m...) } -// Add registers a new route for an HTTP method and path with matching handler -// in the router with optional route-level middleware. -func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { +func (e *Echo) add(host, method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { name := handlerName(handler) - e.router.Add(method, path, func(c Context) error { + router := e.findRouter(host) + router.Add(method, path, func(c Context) error { h := handler // Chain middleware for i := len(middleware) - 1; i >= 0; i-- { @@ -498,6 +513,20 @@ func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...Middl return r } +// Add registers a new route for an HTTP method and path with matching handler +// in the router with optional route-level middleware. +func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { + return e.add("", method, path, handler, middleware...) +} + +// Host creates a new router group for the provided host and optional host-level middleware. +func (e *Echo) Host(name string, m ...MiddlewareFunc) (g *Group) { + e.routers[name] = NewRouter(e) + g = &Group{host: name, echo: e} + g.Use(m...) + return +} + // Group creates a new router group with prefix and optional group-level middleware. func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) { g = &Group{prefix: prefix, echo: e} @@ -570,23 +599,17 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) { h := NotFoundHandler if e.premiddleware == nil { - e.router.Find(r.Method, getPath(r), c) + e.findRouter(r.Host).Find(r.Method, getPath(r), c) h = c.Handler() - for i := len(e.middleware) - 1; i >= 0; i-- { - h = e.middleware[i](h) - } + h = applyMiddleware(h, e.middleware...) } else { h = func(c Context) error { - e.router.Find(r.Method, getPath(r), c) + e.findRouter(r.Host).Find(r.Method, getPath(r), c) h := c.Handler() - for i := len(e.middleware) - 1; i >= 0; i-- { - h = e.middleware[i](h) - } + h = applyMiddleware(h, e.middleware...) return h(c) } - for i := len(e.premiddleware) - 1; i >= 0; i-- { - h = e.premiddleware[i](h) - } + h = applyMiddleware(h, e.premiddleware...) } // Execute chain @@ -605,25 +628,46 @@ func (e *Echo) Start(address string) error { } // StartTLS starts an HTTPS server. -func (e *Echo) StartTLS(address string, certFile, keyFile string) (err error) { - if certFile == "" || keyFile == "" { - return errors.New("invalid tls configuration") +// If `certFile` or `keyFile` is `string` the values are treated as file paths. +// If `certFile` or `keyFile` is `[]byte` the values are treated as the certificate or key as-is. +func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err error) { + var cert []byte + if cert, err = filepathOrContent(certFile); err != nil { + return + } + + var key []byte + if key, err = filepathOrContent(keyFile); err != nil { + return } + s := e.TLSServer s.TLSConfig = new(tls.Config) s.TLSConfig.Certificates = make([]tls.Certificate, 1) - s.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) - if err != nil { + if s.TLSConfig.Certificates[0], err = tls.X509KeyPair(cert, key); err != nil { return } + return e.startTLS(address) } +func filepathOrContent(fileOrContent interface{}) (content []byte, err error) { + switch v := fileOrContent.(type) { + case string: + return ioutil.ReadFile(v) + case []byte: + return v, nil + default: + return nil, ErrInvalidCertOrKeyType + } +} + // StartAutoTLS starts an HTTPS server using certificates automatically installed from https://letsencrypt.org. func (e *Echo) StartAutoTLS(address string) error { s := e.TLSServer s.TLSConfig = new(tls.Config) s.TLSConfig.GetCertificate = e.AutoTLSManager.GetCertificate + s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, acme.ALPNProto) return e.startTLS(address) } @@ -742,6 +786,15 @@ func getPath(r *http.Request) string { return path } +func (e *Echo) findRouter(host string) *Router { + if len(e.routers) > 0 { + if r, ok := e.routers[host]; ok { + return r + } + } + return e.router +} + func handlerName(h HandlerFunc) string { t := reflect.ValueOf(h).Type() if t.Kind() == reflect.Func { @@ -764,13 +817,14 @@ type tcpKeepAliveListener struct { } func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { - tc, err := ln.AcceptTCP() - if err != nil { + if c, err = ln.AcceptTCP(); err != nil { + return + } else if err = c.(*net.TCPConn).SetKeepAlive(true); err != nil { + return + } else if err = c.(*net.TCPConn).SetKeepAlivePeriod(3 * time.Minute); err != nil { return } - tc.SetKeepAlive(true) - tc.SetKeepAlivePeriod(3 * time.Minute) - return tc, nil + return } func newListener(address string) (*tcpKeepAliveListener, error) { @@ -780,3 +834,10 @@ func newListener(address string) (*tcpKeepAliveListener, error) { } return &tcpKeepAliveListener{l.(*net.TCPListener)}, nil } + +func applyMiddleware(h HandlerFunc, middleware ...MiddlewareFunc) HandlerFunc { + for i := len(middleware) - 1; i >= 0; i-- { + h = middleware[i](h) + } + return h +} diff --git a/vendor/github.com/labstack/echo/v4/go.mod b/vendor/github.com/labstack/echo/v4/go.mod index 2853cba5..d76b9843 100644 --- a/vendor/github.com/labstack/echo/v4/go.mod +++ b/vendor/github.com/labstack/echo/v4/go.mod @@ -1,13 +1,15 @@ module github.com/labstack/echo/v4 +go 1.12 + require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible - github.com/labstack/gommon v0.2.8 - github.com/mattn/go-colorable v0.0.9 // indirect - github.com/mattn/go-isatty v0.0.4 // indirect + github.com/labstack/gommon v0.2.9 github.com/stretchr/testify v1.3.0 - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 - golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 - golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc // indirect + github.com/valyala/fasttemplate v1.0.1 + golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 + golang.org/x/net v0.0.0-20190607181551-461777fb6f67 // indirect + golang.org/x/sys v0.0.0-20190609082536-301114b31cce // indirect + golang.org/x/text v0.3.2 // indirect + golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3 // indirect ) diff --git a/vendor/github.com/labstack/echo/v4/go.sum b/vendor/github.com/labstack/echo/v4/go.sum index e6981931..48c5b8f1 100644 --- a/vendor/github.com/labstack/echo/v4/go.sum +++ b/vendor/github.com/labstack/echo/v4/go.sum @@ -1,23 +1,53 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0= github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/labstack/gommon v0.2.9 h1:heVeuAYtevIQVYkGj6A41dtfT91LrvFG220lavpWhrU= +github.com/labstack/gommon v0.2.9/go.mod h1:E8ZTmW9vw5az5/ZyHWCp0Lw4OH2ecsaBP1C/NKavGG4= +github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QINDnvyZuTaACm9ofY+PRh+5vFz4oxBZeF8= -github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw= -golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 h1:YbZJ76lQ1BqNhVe7dKTSB67wDrc2VPRR75IyGyyPDX8= -golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc h1:WiYx1rIFmx8c0mXAFtv5D/mHyKe1+jmuP7PViuwqwuQ= -golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190607181551-461777fb6f67 h1:rJJxsykSlULwd2P2+pg/rtnwN2FrWp4IuCxOSyS0V00= +golang.org/x/net v0.0.0-20190607181551-461777fb6f67/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2 h1:T5DasATyLQfmbTpfEXx/IOL9vfjzW6up+ZDkmHvIf2s= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190609082536-301114b31cce/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= diff --git a/vendor/github.com/labstack/echo/v4/group.go b/vendor/github.com/labstack/echo/v4/group.go index 3e3732b6..5d958253 100644 --- a/vendor/github.com/labstack/echo/v4/group.go +++ b/vendor/github.com/labstack/echo/v4/group.go @@ -2,7 +2,6 @@ package echo import ( "net/http" - "path" ) type ( @@ -10,6 +9,8 @@ type ( // routes that share a common middleware or functionality that should be separate // from the parent echo instance while still inheriting from it. Group struct { + common + host string prefix string middleware []MiddlewareFunc echo *Echo @@ -19,13 +20,13 @@ type ( // Use implements `Echo#Use()` for sub-routes within the Group. func (g *Group) Use(middleware ...MiddlewareFunc) { g.middleware = append(g.middleware, middleware...) + if len(g.middleware) == 0 { + return + } // Allow all requests to reach the group as they might get dropped if router // doesn't find a match, making none of the group middleware process. - for _, p := range []string{"", "/*"} { - g.echo.Any(path.Clean(g.prefix+p), func(c Context) error { - return NotFoundHandler(c) - }, g.middleware...) - } + g.Any("", NotFoundHandler) + g.Any("/*", NotFoundHandler) } // CONNECT implements `Echo#CONNECT()` for sub-routes within the Group. @@ -92,21 +93,23 @@ func (g *Group) Match(methods []string, path string, handler HandlerFunc, middle } // Group creates a new sub-group with prefix and optional sub-group-level middleware. -func (g *Group) Group(prefix string, middleware ...MiddlewareFunc) *Group { +func (g *Group) Group(prefix string, middleware ...MiddlewareFunc) (sg *Group) { m := make([]MiddlewareFunc, 0, len(g.middleware)+len(middleware)) m = append(m, g.middleware...) m = append(m, middleware...) - return g.echo.Group(g.prefix+prefix, m...) + sg = g.echo.Group(g.prefix+prefix, m...) + sg.host = g.host + return } // Static implements `Echo#Static()` for sub-routes within the Group. func (g *Group) Static(prefix, root string) { - static(g, prefix, root) + g.static(prefix, root, g.GET) } // File implements `Echo#File()` for sub-routes within the Group. func (g *Group) File(path, file string) { - g.echo.File(g.prefix+path, file) + g.file(g.prefix+path, file, g.GET) } // Add implements `Echo#Add()` for sub-routes within the Group. @@ -117,5 +120,5 @@ func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...Midd m := make([]MiddlewareFunc, 0, len(g.middleware)+len(middleware)) m = append(m, g.middleware...) m = append(m, middleware...) - return g.echo.Add(method, g.prefix+path, handler, m...) + return g.echo.add(g.host, method, g.prefix+path, handler, m...) } diff --git a/vendor/github.com/labstack/echo/v4/middleware/compress.go b/vendor/github.com/labstack/echo/v4/middleware/compress.go index 19052064..89da16ef 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/compress.go +++ b/vendor/github.com/labstack/echo/v4/middleware/compress.go @@ -111,6 +111,9 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) { func (w *gzipResponseWriter) Flush() { w.Writer.(*gzip.Writer).Flush() + if flusher, ok := w.ResponseWriter.(http.Flusher); ok { + flusher.Flush() + } } func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { diff --git a/vendor/github.com/labstack/echo/v4/middleware/cors.go b/vendor/github.com/labstack/echo/v4/middleware/cors.go index c61c7125..5dfe31f9 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/cors.go +++ b/vendor/github.com/labstack/echo/v4/middleware/cors.go @@ -102,6 +102,10 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc { allowOrigin = o break } + if matchSubdomain(origin, o) { + allowOrigin = origin + break + } } // Simple request diff --git a/vendor/github.com/labstack/echo/v4/middleware/jwt.go b/vendor/github.com/labstack/echo/v4/middleware/jwt.go index 861d3142..d4420246 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/jwt.go +++ b/vendor/github.com/labstack/echo/v4/middleware/jwt.go @@ -26,10 +26,14 @@ type ( // It may be used to define a custom JWT error. ErrorHandler JWTErrorHandler - // Signing key to validate token. - // Required. + // Signing key to validate token. Used as fallback if SigningKeys has length 0. + // Required. This or SigningKeys. SigningKey interface{} + // Map of signing keys to validate token with kid field usage. + // Required. This or SigningKey. + SigningKeys map[string]interface{} + // Signing method, used to check token signing method. // Optional. Default value HS256. SigningMethod string @@ -48,6 +52,7 @@ type ( // Possible values: // - "header:<name>" // - "query:<name>" + // - "param:<name>" // - "cookie:<name>" TokenLookup string @@ -110,7 +115,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { if config.Skipper == nil { config.Skipper = DefaultJWTConfig.Skipper } - if config.SigningKey == nil { + if config.SigningKey == nil && len(config.SigningKeys) == 0 { panic("echo: jwt middleware requires signing key") } if config.SigningMethod == "" { @@ -133,6 +138,15 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { if t.Method.Alg() != config.SigningMethod { return nil, fmt.Errorf("unexpected jwt signing method=%v", t.Header["alg"]) } + if len(config.SigningKeys) > 0 { + if kid, ok := t.Header["kid"].(string); ok { + if key, ok := config.SigningKeys[kid]; ok { + return key, nil + } + } + return nil, fmt.Errorf("unexpected jwt key id=%v", t.Header["kid"]) + } + return config.SigningKey, nil } @@ -142,6 +156,8 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { switch parts[0] { case "query": extractor = jwtFromQuery(parts[1]) + case "param": + extractor = jwtFromParam(parts[1]) case "cookie": extractor = jwtFromCookie(parts[1]) } @@ -215,6 +231,17 @@ func jwtFromQuery(param string) jwtExtractor { } } +// jwtFromParam returns a `jwtExtractor` that extracts token from the url param string. +func jwtFromParam(param string) jwtExtractor { + return func(c echo.Context) (string, error) { + token := c.Param(param) + if token == "" { + return "", ErrJWTMissing + } + return token, nil + } +} + // jwtFromCookie returns a `jwtExtractor` that extracts token from the named cookie. func jwtFromCookie(name string) jwtExtractor { return func(c echo.Context) (string, error) { diff --git a/vendor/github.com/labstack/echo/v4/middleware/key_auth.go b/vendor/github.com/labstack/echo/v4/middleware/key_auth.go index fe01e23e..94cfd142 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/key_auth.go +++ b/vendor/github.com/labstack/echo/v4/middleware/key_auth.go @@ -99,11 +99,14 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc { } valid, err := config.Validator(key, c) if err != nil { - return err + return &echo.HTTPError{ + Code: http.StatusUnauthorized, + Message: "invalid key", + Internal: err, + } } else if valid { return next(c) } - return echo.ErrUnauthorized } } diff --git a/vendor/github.com/labstack/echo/v4/middleware/logger.go b/vendor/github.com/labstack/echo/v4/middleware/logger.go index b2e48347..6fd59efb 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/logger.go +++ b/vendor/github.com/labstack/echo/v4/middleware/logger.go @@ -2,6 +2,7 @@ package middleware import ( "bytes" + "encoding/json" "io" "os" "strconv" @@ -20,7 +21,7 @@ type ( // Skipper defines a function to skip middleware. Skipper Skipper - // Tags to constructed the logger format. + // Tags to construct the logger format. // // - time_unix // - time_unix_nano @@ -175,7 +176,10 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc { return buf.WriteString(s) case "error": if err != nil { - return buf.WriteString(err.Error()) + // Error may contain invalid JSON e.g. `"` + b, _ := json.Marshal(err.Error()) + b = b[1 : len(b)-1] + return buf.Write(b) } case "latency": l := stop.Sub(start) diff --git a/vendor/github.com/labstack/echo/v4/middleware/proxy.go b/vendor/github.com/labstack/echo/v4/middleware/proxy.go index 9d67f445..532346d5 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/proxy.go +++ b/vendor/github.com/labstack/echo/v4/middleware/proxy.go @@ -200,7 +200,7 @@ func Proxy(balancer ProxyBalancer) echo.MiddlewareFunc { func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc { // Defaults if config.Skipper == nil { - config.Skipper = DefaultLoggerConfig.Skipper + config.Skipper = DefaultProxyConfig.Skipper } if config.Balancer == nil { panic("echo: proxy middleware requires balancer") diff --git a/vendor/github.com/labstack/echo/v4/middleware/redirect.go b/vendor/github.com/labstack/echo/v4/middleware/redirect.go index 30a2e403..813e5b85 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/redirect.go +++ b/vendor/github.com/labstack/echo/v4/middleware/redirect.go @@ -21,7 +21,7 @@ type RedirectConfig struct { // 2) return the appropriate redirect url. type redirectLogic func(scheme, host, uri string) (ok bool, url string) -const www = "www" +const www = "www." // DefaultRedirectConfig is the default Redirect middleware config. var DefaultRedirectConfig = RedirectConfig{ @@ -60,7 +60,7 @@ func HTTPSWWWRedirect() echo.MiddlewareFunc { // See `HTTPSWWWRedirect()`. func HTTPSWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { return redirect(config, func(scheme, host, uri string) (ok bool, url string) { - if ok = scheme != "https" && host[:3] != www; ok { + if ok = scheme != "https" && host[:4] != www; ok { url = "https://www." + host + uri } return @@ -80,7 +80,7 @@ func HTTPSNonWWWRedirect() echo.MiddlewareFunc { func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { return redirect(config, func(scheme, host, uri string) (ok bool, url string) { if ok = scheme != "https"; ok { - if host[:3] == www { + if host[:4] == www { host = host[4:] } url = "https://" + host + uri @@ -101,7 +101,7 @@ func WWWRedirect() echo.MiddlewareFunc { // See `WWWRedirect()`. func WWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { return redirect(config, func(scheme, host, uri string) (ok bool, url string) { - if ok = host[:3] != www; ok { + if ok = host[:4] != www; ok { url = scheme + "://www." + host + uri } return @@ -120,7 +120,7 @@ func NonWWWRedirect() echo.MiddlewareFunc { // See `NonWWWRedirect()`. func NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { return redirect(config, func(scheme, host, uri string) (ok bool, url string) { - if ok = host[:3] == www; ok { + if ok = host[:4] == www; ok { url = scheme + "://" + host[4:] + uri } return diff --git a/vendor/github.com/labstack/echo/v4/middleware/secure.go b/vendor/github.com/labstack/echo/v4/middleware/secure.go index 8839c879..77a1487f 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/secure.go +++ b/vendor/github.com/labstack/echo/v4/middleware/secure.go @@ -53,6 +53,19 @@ type ( // trusted web page context. // Optional. Default value "". ContentSecurityPolicy string `yaml:"content_security_policy"` + + // CSPReportOnly would use the `Content-Security-Policy-Report-Only` header instead + // of the `Content-Security-Policy` header. This allows iterative updates of the + // content security policy by only reporting the violations that would + // have occurred instead of blocking the resource. + // Optional. Default value false. + CSPReportOnly bool `yaml:"csp_report_only"` + + // HSTSPreloadEnabled will add the preload tag in the `Strict Transport Security` + // header, which enables the domain to be included in the HSTS preload list + // maintained by Chrome (and used by Firefox and Safari): https://hstspreload.org/ + // Optional. Default value false. + HSTSPreloadEnabled bool `yaml:"hsts_preload_enabled"` } ) @@ -63,6 +76,7 @@ var ( XSSProtection: "1; mode=block", ContentTypeNosniff: "nosniff", XFrameOptions: "SAMEORIGIN", + HSTSPreloadEnabled: false, } ) @@ -105,10 +119,17 @@ func SecureWithConfig(config SecureConfig) echo.MiddlewareFunc { if !config.HSTSExcludeSubdomains { subdomains = "; includeSubdomains" } + if config.HSTSPreloadEnabled { + subdomains = fmt.Sprintf("%s; preload", subdomains) + } res.Header().Set(echo.HeaderStrictTransportSecurity, fmt.Sprintf("max-age=%d%s", config.HSTSMaxAge, subdomains)) } if config.ContentSecurityPolicy != "" { - res.Header().Set(echo.HeaderContentSecurityPolicy, config.ContentSecurityPolicy) + if config.CSPReportOnly { + res.Header().Set(echo.HeaderContentSecurityPolicyReportOnly, config.ContentSecurityPolicy) + } else { + res.Header().Set(echo.HeaderContentSecurityPolicy, config.ContentSecurityPolicy) + } } return next(c) } diff --git a/vendor/github.com/labstack/echo/v4/middleware/slash.go b/vendor/github.com/labstack/echo/v4/middleware/slash.go index 61d6e30b..0492b334 100644 --- a/vendor/github.com/labstack/echo/v4/middleware/slash.go +++ b/vendor/github.com/labstack/echo/v4/middleware/slash.go @@ -1,6 +1,8 @@ package middleware import ( + "strings" + "github.com/labstack/echo/v4" ) @@ -49,7 +51,7 @@ func AddTrailingSlashWithConfig(config TrailingSlashConfig) echo.MiddlewareFunc url := req.URL path := url.Path qs := c.QueryString() - if path != "/" && path[len(path)-1] != '/' { + if !strings.HasSuffix(path, "/") { path += "/" uri := path if qs != "" { @@ -97,7 +99,7 @@ func RemoveTrailingSlashWithConfig(config TrailingSlashConfig) echo.MiddlewareFu path := url.Path qs := c.QueryString() l := len(path) - 1 - if l >= 0 && path != "/" && path[l] == '/' { + if l > 0 && strings.HasSuffix(path, "/") { path = path[:l] uri := path if qs != "" { diff --git a/vendor/github.com/labstack/echo/v4/middleware/util.go b/vendor/github.com/labstack/echo/v4/middleware/util.go new file mode 100644 index 00000000..ab951a0e --- /dev/null +++ b/vendor/github.com/labstack/echo/v4/middleware/util.go @@ -0,0 +1,54 @@ +package middleware + +import ( + "strings" +) + +func matchScheme(domain, pattern string) bool { + didx := strings.Index(domain, ":") + pidx := strings.Index(pattern, ":") + return didx != -1 && pidx != -1 && domain[:didx] == pattern[:pidx] +} + +// matchSubdomain compares authority with wildcard +func matchSubdomain(domain, pattern string) bool { + if !matchScheme(domain, pattern) { + return false + } + didx := strings.Index(domain, "://") + pidx := strings.Index(pattern, "://") + if didx == -1 || pidx == -1 { + return false + } + domAuth := domain[didx+3:] + // to avoid long loop by invalid long domain + if len(domAuth) > 253 { + return false + } + patAuth := pattern[pidx+3:] + + domComp := strings.Split(domAuth, ".") + patComp := strings.Split(patAuth, ".") + for i := len(domComp)/2 - 1; i >= 0; i-- { + opp := len(domComp) - 1 - i + domComp[i], domComp[opp] = domComp[opp], domComp[i] + } + for i := len(patComp)/2 - 1; i >= 0; i-- { + opp := len(patComp) - 1 - i + patComp[i], patComp[opp] = patComp[opp], patComp[i] + } + + for i, v := range domComp { + if len(patComp) <= i { + return false + } + p := patComp[i] + if p == "*" { + return true + } + if p != v { + return false + } + } + return false +} diff --git a/vendor/github.com/labstack/echo/v4/response.go b/vendor/github.com/labstack/echo/v4/response.go index eb2d988d..ca7405c5 100644 --- a/vendor/github.com/labstack/echo/v4/response.go +++ b/vendor/github.com/labstack/echo/v4/response.go @@ -67,7 +67,10 @@ func (r *Response) WriteHeader(code int) { // Write writes the data to the connection as part of an HTTP reply. func (r *Response) Write(b []byte) (n int, err error) { if !r.Committed { - r.WriteHeader(http.StatusOK) + if r.Status == 0 { + r.Status = http.StatusOK + } + r.WriteHeader(r.Status) } n, err = r.Writer.Write(b) r.Size += int64(n) diff --git a/vendor/github.com/labstack/echo/v4/router.go b/vendor/github.com/labstack/echo/v4/router.go index 73f0b68b..8d3a0180 100644 --- a/vendor/github.com/labstack/echo/v4/router.go +++ b/vendor/github.com/labstack/echo/v4/router.go @@ -33,6 +33,7 @@ type ( propfind HandlerFunc put HandlerFunc trace HandlerFunc + report HandlerFunc } ) @@ -57,7 +58,7 @@ func NewRouter(e *Echo) *Router { func (r *Router) Add(method, path string, h HandlerFunc) { // Validate path if path == "" { - panic("echo: path cannot be empty") + path = "/" } if path[0] != '/' { path = "/" + path @@ -79,14 +80,13 @@ func (r *Router) Add(method, path string, h HandlerFunc) { if i == l { r.insert(method, path[:i], h, pkind, ppath, pnames) - return + } else { + r.insert(method, path[:i], nil, pkind, "", nil) } - r.insert(method, path[:i], nil, pkind, "", nil) } else if path[i] == '*' { r.insert(method, path[:i], nil, skind, "", nil) pnames = append(pnames, "*") r.insert(method, path[:i+1], h, akind, ppath, pnames) - return } } @@ -248,6 +248,8 @@ func (n *node) addHandler(method string, h HandlerFunc) { n.methodHandler.put = h case http.MethodTrace: n.methodHandler.trace = h + case REPORT: + n.methodHandler.report = h } } @@ -273,6 +275,8 @@ func (n *node) findHandler(method string) HandlerFunc { return n.methodHandler.put case http.MethodTrace: return n.methodHandler.trace + case REPORT: + return n.methodHandler.report default: return nil } |