diff options
Diffstat (limited to 'vendor')
17 files changed, 335 insertions, 143 deletions
diff --git a/vendor/github.com/labstack/echo/context.go b/vendor/github.com/labstack/echo/context.go index 242eec26..54fa71ad 100644 --- a/vendor/github.com/labstack/echo/context.go +++ b/vendor/github.com/labstack/echo/context.go @@ -494,14 +494,9 @@ func (c *context) Stream(code int, contentType string, r io.Reader) (err error) } func (c *context) File(file string) (err error) { - file, err = url.QueryUnescape(file) // Issue #839 - if err != nil { - return - } - f, err := os.Open(file) if err != nil { - return ErrNotFound + return NotFoundHandler(c) } defer f.Close() @@ -510,7 +505,7 @@ func (c *context) File(file string) (err error) { file = filepath.Join(file, indexPage) f, err = os.Open(file) if err != nil { - return ErrNotFound + return NotFoundHandler(c) } defer f.Close() if fi, err = f.Stat(); err != nil { @@ -530,7 +525,7 @@ func (c *context) Inline(file, name string) (err error) { } func (c *context) contentDisposition(file, name, dispositionType string) (err error) { - c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%s", dispositionType, name)) + c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%q", dispositionType, name)) c.File(file) return } diff --git a/vendor/github.com/labstack/echo/echo.go b/vendor/github.com/labstack/echo/echo.go index baa92fde..77c238d0 100644 --- a/vendor/github.com/labstack/echo/echo.go +++ b/vendor/github.com/labstack/echo/echo.go @@ -72,6 +72,7 @@ type ( TLSServer *http.Server Listener net.Listener TLSListener net.Listener + AutoTLSManager autocert.Manager DisableHTTP2 bool Debug bool HideBanner bool @@ -79,22 +80,22 @@ type ( Binder Binder Validator Validator Renderer Renderer - AutoTLSManager autocert.Manager // Mutex sync.RWMutex Logger Logger } // Route contains a handler and information for matching against requests. Route struct { - Method string `json:"method"` - Path string `json:"path"` - Handler string `json:"handler"` + Method string `json:"method"` + Path string `json:"path"` + Name string `json:"name"` } // HTTPError represents an error that occurred while handling a request. HTTPError struct { Code int Message interface{} + Inner error // Stores the error returned by an external dependency } // MiddlewareFunc defines a function to process middleware. @@ -121,7 +122,7 @@ type ( // i is the interface for Echo and Group. i interface { - GET(string, HandlerFunc, ...MiddlewareFunc) + GET(string, HandlerFunc, ...MiddlewareFunc) *Route } ) @@ -212,7 +213,7 @@ const ( ) const ( - version = "3.1.0" + version = "3.2.5" website = "https://echo.labstack.com" // http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo banner = ` @@ -282,7 +283,7 @@ func New() (e *Echo) { e.TLSServer.Handler = e e.HTTPErrorHandler = e.DefaultHTTPErrorHandler e.Binder = &DefaultBinder{} - e.Logger.SetLevel(log.OFF) + e.Logger.SetLevel(log.ERROR) e.stdLogger = stdLog.New(e.Logger.Output(), e.Logger.Prefix()+": ", 0) e.pool.New = func() interface{} { return e.NewContext(nil, nil) @@ -319,6 +320,9 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) { if he, ok := err.(*HTTPError); ok { code = he.Code msg = he.Message + if he.Inner != nil { + msg = fmt.Sprintf("%v, %v", err, he.Inner) + } } else if e.Debug { msg = err.Error() } else { @@ -328,19 +332,19 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) { msg = Map{"message": msg} } + e.Logger.Error(err) + + // Send response if !c.Response().Committed { if c.Request().Method == HEAD { // Issue #608 - if err := c.NoContent(code); err != nil { - goto ERROR - } + err = c.NoContent(code) } else { - if err := c.JSON(code, msg); err != nil { - goto ERROR - } + err = c.JSON(code, msg) + } + if err != nil { + e.Logger.Error(err) } } -ERROR: - e.Logger.Error(err) } // Pre adds middleware to the chain which is run before router. @@ -355,104 +359,114 @@ func (e *Echo) Use(middleware ...MiddlewareFunc) { // CONNECT registers a new CONNECT route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(CONNECT, path, h, m...) +func (e *Echo) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(CONNECT, path, h, m...) } // DELETE registers a new DELETE route for a path with matching handler in the router // with optional route-level middleware. -func (e *Echo) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(DELETE, path, h, m...) +func (e *Echo) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(DELETE, path, h, m...) } // GET registers a new GET route for a path with matching handler in the router // with optional route-level middleware. -func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(GET, path, h, m...) +func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(GET, path, h, m...) } // HEAD registers a new HEAD route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(HEAD, path, h, m...) +func (e *Echo) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(HEAD, path, h, m...) } // OPTIONS registers a new OPTIONS route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(OPTIONS, path, h, m...) +func (e *Echo) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(OPTIONS, path, h, m...) } // PATCH registers a new PATCH route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(PATCH, path, h, m...) +func (e *Echo) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(PATCH, path, h, m...) } // POST registers a new POST route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) POST(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(POST, path, h, m...) +func (e *Echo) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(POST, path, h, m...) } // PUT registers a new PUT route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(PUT, path, h, m...) +func (e *Echo) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(PUT, path, h, m...) } // TRACE registers a new TRACE route for a path with matching handler in the // router with optional route-level middleware. -func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) { - e.add(TRACE, path, h, m...) +func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return e.Add(TRACE, path, h, m...) } // Any registers a new route for all HTTP methods and path with matching handler // in the router with optional route-level middleware. -func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) { +func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route { + routes := make([]*Route, 0) for _, m := range methods { - e.add(m, path, handler, middleware...) + routes = append(routes, e.Add(m, path, handler, middleware...)) } + return routes } // Match registers a new route for multiple HTTP methods and path with matching // handler in the router with optional route-level middleware. -func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { +func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route { + routes := make([]*Route, 0) for _, m := range methods { - e.add(m, path, handler, middleware...) + routes = append(routes, e.Add(m, path, handler, middleware...)) } + return routes } // Static registers a new route with path prefix to serve static files from the // provided root directory. -func (e *Echo) Static(prefix, root string) { +func (e *Echo) Static(prefix, root string) *Route { if root == "" { root = "." // For security we want to restrict to CWD. } - static(e, prefix, root) + return static(e, prefix, root) } -func static(i i, prefix, root string) { +func static(i i, prefix, root string) *Route { h := func(c Context) error { - name := filepath.Join(root, path.Clean("/"+c.Param("*"))) // "/"+ for security + p, err := PathUnescape(c.Param("*")) + if err != nil { + return err + } + name := filepath.Join(root, path.Clean("/"+p)) // "/"+ for security return c.File(name) } i.GET(prefix, h) if prefix == "/" { - i.GET(prefix+"*", h) - } else { - i.GET(prefix+"/*", h) + return i.GET(prefix+"*", h) } + + return i.GET(prefix+"/*", h) } // File registers a new route with path to serve a static file. -func (e *Echo) File(path, file string) { - e.GET(path, func(c Context) error { +func (e *Echo) File(path, file string) *Route { + return e.GET(path, func(c Context) error { return c.File(file) }) } -func (e *Echo) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { +// 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 { name := handlerName(handler) e.router.Add(method, path, func(c Context) error { h := handler @@ -463,11 +477,12 @@ func (e *Echo) add(method, path string, handler HandlerFunc, middleware ...Middl return h(c) }) r := &Route{ - Method: method, - Path: path, - Handler: name, + Method: method, + Path: path, + Name: name, } e.router.routes[method+path] = r + return r } // Group creates a new router group with prefix and optional group-level middleware. @@ -479,12 +494,22 @@ func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) { // URI generates a URI from handler. func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string { + name := handlerName(handler) + return e.Reverse(name, params...) +} + +// URL is an alias for `URI` function. +func (e *Echo) URL(h HandlerFunc, params ...interface{}) string { + return e.URI(h, params...) +} + +// Reverse generates an URL from route name and provided parameters. +func (e *Echo) Reverse(name string, params ...interface{}) string { uri := new(bytes.Buffer) ln := len(params) n := 0 - name := handlerName(handler) for _, r := range e.router.routes { - if r.Handler == name { + if r.Name == name { for i, l := 0, len(r.Path); i < l; i++ { if r.Path[i] == ':' && n < ln { for ; i < l && r.Path[i] != '/'; i++ { @@ -502,11 +527,6 @@ func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string { return uri.String() } -// URL is an alias for `URI` function. -func (e *Echo) URL(h HandlerFunc, params ...interface{}) string { - return e.URI(h, params...) -} - // Routes returns the registered routes. func (e *Echo) Routes() []*Route { routes := []*Route{} @@ -653,7 +673,7 @@ func NewHTTPError(code int, message ...interface{}) *HTTPError { // Error makes it compatible with `error` interface. func (he *HTTPError) Error() string { - return fmt.Sprintf("code=%d, message=%s", he.Code, he.Message) + return fmt.Sprintf("code=%d, message=%v", he.Code, he.Message) } // WrapHandler wraps `http.Handler` into `echo.HandlerFunc`. diff --git a/vendor/github.com/labstack/echo/group.go b/vendor/github.com/labstack/echo/group.go index 799a8f90..6ae32372 100644 --- a/vendor/github.com/labstack/echo/group.go +++ b/vendor/github.com/labstack/echo/group.go @@ -21,66 +21,66 @@ func (g *Group) Use(middleware ...MiddlewareFunc) { // 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. g.echo.Any(path.Clean(g.prefix+"/*"), func(c Context) error { - return ErrNotFound + return NotFoundHandler(c) }, g.middleware...) } // CONNECT implements `Echo#CONNECT()` for sub-routes within the Group. -func (g *Group) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(CONNECT, path, h, m...) +func (g *Group) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(CONNECT, path, h, m...) } // DELETE implements `Echo#DELETE()` for sub-routes within the Group. -func (g *Group) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(DELETE, path, h, m...) +func (g *Group) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(DELETE, path, h, m...) } // GET implements `Echo#GET()` for sub-routes within the Group. -func (g *Group) GET(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(GET, path, h, m...) +func (g *Group) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(GET, path, h, m...) } // HEAD implements `Echo#HEAD()` for sub-routes within the Group. -func (g *Group) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(HEAD, path, h, m...) +func (g *Group) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(HEAD, path, h, m...) } // OPTIONS implements `Echo#OPTIONS()` for sub-routes within the Group. -func (g *Group) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(OPTIONS, path, h, m...) +func (g *Group) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(OPTIONS, path, h, m...) } // PATCH implements `Echo#PATCH()` for sub-routes within the Group. -func (g *Group) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(PATCH, path, h, m...) +func (g *Group) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(PATCH, path, h, m...) } // POST implements `Echo#POST()` for sub-routes within the Group. -func (g *Group) POST(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(POST, path, h, m...) +func (g *Group) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(POST, path, h, m...) } // PUT implements `Echo#PUT()` for sub-routes within the Group. -func (g *Group) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(PUT, path, h, m...) +func (g *Group) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(PUT, path, h, m...) } // TRACE implements `Echo#TRACE()` for sub-routes within the Group. -func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) { - g.add(TRACE, path, h, m...) +func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { + return g.Add(TRACE, path, h, m...) } // Any implements `Echo#Any()` for sub-routes within the Group. func (g *Group) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) { for _, m := range methods { - g.add(m, path, handler, middleware...) + g.Add(m, path, handler, middleware...) } } // Match implements `Echo#Match()` for sub-routes within the Group. func (g *Group) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { for _, m := range methods { - g.add(m, path, handler, middleware...) + g.Add(m, path, handler, middleware...) } } @@ -102,12 +102,13 @@ func (g *Group) File(path, file string) { g.echo.File(g.prefix+path, file) } -func (g *Group) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { +// Add implements `Echo#Add()` for sub-routes within the Group. +func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { // Combine into a new slice to avoid accidentally passing the same slice for // multiple routes, which would lead to later add() calls overwriting the // middleware from earlier calls. m := []MiddlewareFunc{} m = append(m, g.middleware...) m = append(m, middleware...) - g.echo.add(method, g.prefix+path, handler, m...) + return g.echo.Add(method, g.prefix+path, handler, m...) } diff --git a/vendor/github.com/labstack/echo/middleware/basic_auth.go b/vendor/github.com/labstack/echo/middleware/basic_auth.go index c1f34c8f..ae80da95 100644 --- a/vendor/github.com/labstack/echo/middleware/basic_auth.go +++ b/vendor/github.com/labstack/echo/middleware/basic_auth.go @@ -3,6 +3,7 @@ package middleware import ( "encoding/base64" "strconv" + "strings" "github.com/labstack/echo" ) @@ -27,7 +28,7 @@ type ( ) const ( - basic = "Basic" + basic = "basic" defaultRealm = "Restricted" ) @@ -54,7 +55,7 @@ func BasicAuth(fn BasicAuthValidator) echo.MiddlewareFunc { func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc { // Defaults if config.Validator == nil { - panic("basic-auth middleware requires a validator function") + panic("echo: basic-auth middleware requires a validator function") } if config.Skipper == nil { config.Skipper = DefaultBasicAuthConfig.Skipper @@ -72,7 +73,7 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc { auth := c.Request().Header.Get(echo.HeaderAuthorization) l := len(basic) - if len(auth) > l+1 && auth[:l] == basic { + if len(auth) > l+1 && strings.ToLower(auth[:l]) == basic { b, err := base64.StdEncoding.DecodeString(auth[l+1:]) if err != nil { return err diff --git a/vendor/github.com/labstack/echo/middleware/body_dump.go b/vendor/github.com/labstack/echo/middleware/body_dump.go new file mode 100644 index 00000000..88b75ee1 --- /dev/null +++ b/vendor/github.com/labstack/echo/middleware/body_dump.go @@ -0,0 +1,112 @@ +package middleware + +import ( + "bufio" + "bytes" + "io/ioutil" + "net" + "net/http" + + "io" + + "github.com/labstack/echo" +) + +type ( + // BodyDumpConfig defines the config for BodyDump middleware. + BodyDumpConfig struct { + // Skipper defines a function to skip middleware. + Skipper Skipper + + // Handler receives request and response payload. + // Required. + Handler BodyDumpHandler + } + + // BodyDumpHandler receives the request and response payload. + BodyDumpHandler func(echo.Context, []byte, []byte) + + bodyDumpResponseWriter struct { + io.Writer + http.ResponseWriter + } +) + +var ( + // DefaultBodyDumpConfig is the default Gzip middleware config. + DefaultBodyDumpConfig = BodyDumpConfig{ + Skipper: DefaultSkipper, + } +) + +// BodyDump returns a BodyDump middleware. +// +// BodyLimit middleware captures the request and response payload and calls the +// registered handler. +func BodyDump(handler BodyDumpHandler) echo.MiddlewareFunc { + c := DefaultBodyDumpConfig + c.Handler = handler + return BodyDumpWithConfig(c) +} + +// BodyDumpWithConfig returns a BodyDump middleware with config. +// See: `BodyDump()`. +func BodyDumpWithConfig(config BodyDumpConfig) echo.MiddlewareFunc { + // Defaults + if config.Handler == nil { + panic("echo: body-dump middleware requires a handler function") + } + if config.Skipper == nil { + config.Skipper = DefaultBodyDumpConfig.Skipper + } + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) (err error) { + if config.Skipper(c) { + return next(c) + } + + // Request + reqBody := []byte{} + if c.Request().Body != nil { // Read + reqBody, _ = ioutil.ReadAll(c.Request().Body) + } + c.Request().Body = ioutil.NopCloser(bytes.NewBuffer(reqBody)) // Reset + + // Response + resBody := new(bytes.Buffer) + mw := io.MultiWriter(c.Response().Writer, resBody) + writer := &bodyDumpResponseWriter{Writer: mw, ResponseWriter: c.Response().Writer} + c.Response().Writer = writer + + if err = next(c); err != nil { + c.Error(err) + } + + // Callback + config.Handler(c, reqBody, resBody.Bytes()) + + return + } + } +} + +func (w *bodyDumpResponseWriter) WriteHeader(code int) { + w.ResponseWriter.WriteHeader(code) +} + +func (w *bodyDumpResponseWriter) Write(b []byte) (int, error) { + return w.Writer.Write(b) +} + +func (w *bodyDumpResponseWriter) Flush() { + w.ResponseWriter.(http.Flusher).Flush() +} + +func (w *bodyDumpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + return w.ResponseWriter.(http.Hijacker).Hijack() +} + +func (w *bodyDumpResponseWriter) CloseNotify() <-chan bool { + return w.ResponseWriter.(http.CloseNotifier).CloseNotify() +} diff --git a/vendor/github.com/labstack/echo/middleware/body_limit.go b/vendor/github.com/labstack/echo/middleware/body_limit.go index a2ff8d62..b964cd29 100644 --- a/vendor/github.com/labstack/echo/middleware/body_limit.go +++ b/vendor/github.com/labstack/echo/middleware/body_limit.go @@ -30,7 +30,7 @@ type ( ) var ( - // DefaultBodyLimitConfig is the default Gzip middleware config. + // DefaultBodyLimitConfig is the default BodyLimit middleware config. DefaultBodyLimitConfig = BodyLimitConfig{ Skipper: DefaultSkipper, } @@ -60,7 +60,7 @@ func BodyLimitWithConfig(config BodyLimitConfig) echo.MiddlewareFunc { limit, err := bytes.Parse(config.Limit) if err != nil { - panic(fmt.Errorf("invalid body-limit=%s", config.Limit)) + panic(fmt.Errorf("echo: invalid body-limit=%s", config.Limit)) } config.limit = limit pool := limitedReaderPool(config) diff --git a/vendor/github.com/labstack/echo/middleware/compress.go b/vendor/github.com/labstack/echo/middleware/compress.go index cffadbd1..1615624c 100644 --- a/vendor/github.com/labstack/echo/middleware/compress.go +++ b/vendor/github.com/labstack/echo/middleware/compress.go @@ -67,7 +67,7 @@ func GzipWithConfig(config GzipConfig) echo.MiddlewareFunc { res := c.Response() res.Header().Add(echo.HeaderVary, echo.HeaderAcceptEncoding) if strings.Contains(c.Request().Header.Get(echo.HeaderAcceptEncoding), gzipScheme) { - res.Header().Add(echo.HeaderContentEncoding, gzipScheme) // Issue #806 + res.Header().Set(echo.HeaderContentEncoding, gzipScheme) // Issue #806 rw := res.Writer w, err := gzip.NewWriterLevel(rw, config.Level) if err != nil { @@ -98,6 +98,7 @@ func (w *gzipResponseWriter) WriteHeader(code int) { if code == http.StatusNoContent { // Issue #489 w.ResponseWriter.Header().Del(echo.HeaderContentEncoding) } + w.Header().Del(echo.HeaderContentLength) // Issue #444 w.ResponseWriter.WriteHeader(code) } diff --git a/vendor/github.com/labstack/echo/middleware/jwt.go b/vendor/github.com/labstack/echo/middleware/jwt.go index 5d2072e7..47d885b0 100644 --- a/vendor/github.com/labstack/echo/middleware/jwt.go +++ b/vendor/github.com/labstack/echo/middleware/jwt.go @@ -1,7 +1,6 @@ package middleware import ( - "errors" "fmt" "net/http" "reflect" @@ -57,6 +56,12 @@ const ( AlgorithmHS256 = "HS256" ) +// Errors +var ( + ErrJWTMissing = echo.NewHTTPError(http.StatusBadRequest, "Missing or malformed jwt") + ErrJWTInvalid = echo.NewHTTPError(http.StatusUnauthorized, "Invalid or expired jwt") +) + var ( // DefaultJWTConfig is the default JWT auth middleware config. DefaultJWTConfig = JWTConfig{ @@ -77,7 +82,7 @@ var ( // // See: https://jwt.io/introduction // See `JWTConfig.TokenLookup` -func JWT(key []byte) echo.MiddlewareFunc { +func JWT(key interface{}) echo.MiddlewareFunc { c := DefaultJWTConfig c.SigningKey = key return JWTWithConfig(c) @@ -134,14 +139,15 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { auth, err := extractor(c) if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, err.Error()) + return err } token := new(jwt.Token) // Issue #647, #656 if _, ok := config.Claims.(jwt.MapClaims); ok { token, err = jwt.Parse(auth, config.keyFunc) } else { - claims := reflect.ValueOf(config.Claims).Interface().(jwt.Claims) + t := reflect.ValueOf(config.Claims).Type().Elem() + claims := reflect.New(t).Interface().(jwt.Claims) token, err = jwt.ParseWithClaims(auth, claims, config.keyFunc) } if err == nil && token.Valid { @@ -149,7 +155,11 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { c.Set(config.ContextKey, token) return next(c) } - return echo.ErrUnauthorized + return &echo.HTTPError{ + Code: ErrJWTInvalid.Code, + Message: ErrJWTInvalid.Message, + Inner: err, + } } } } @@ -162,7 +172,7 @@ func jwtFromHeader(header string, authScheme string) jwtExtractor { if len(auth) > l+1 && auth[:l] == authScheme { return auth[l+1:], nil } - return "", errors.New("Missing or invalid jwt in the request header") + return "", ErrJWTMissing } } @@ -171,7 +181,7 @@ func jwtFromQuery(param string) jwtExtractor { return func(c echo.Context) (string, error) { token := c.QueryParam(param) if token == "" { - return "", errors.New("Missing jwt in the query string") + return "", ErrJWTMissing } return token, nil } @@ -182,7 +192,7 @@ func jwtFromCookie(name string) jwtExtractor { return func(c echo.Context) (string, error) { cookie, err := c.Cookie(name) if err != nil { - return "", errors.New("Missing jwt in the cookie") + return "", ErrJWTMissing } return cookie.Value, nil } diff --git a/vendor/github.com/labstack/echo/middleware/key_auth.go b/vendor/github.com/labstack/echo/middleware/key_auth.go index 5ef87e3d..24625260 100644 --- a/vendor/github.com/labstack/echo/middleware/key_auth.go +++ b/vendor/github.com/labstack/echo/middleware/key_auth.go @@ -72,7 +72,7 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc { config.KeyLookup = DefaultKeyAuthConfig.KeyLookup } if config.Validator == nil { - panic("key-auth middleware requires a validator function") + panic("echo: key-auth middleware requires a validator function") } // Initialize diff --git a/vendor/github.com/labstack/echo/middleware/proxy.go b/vendor/github.com/labstack/echo/middleware/proxy.go index 7eb24abf..4f55f39d 100644 --- a/vendor/github.com/labstack/echo/middleware/proxy.go +++ b/vendor/github.com/labstack/echo/middleware/proxy.go @@ -1,7 +1,6 @@ package middleware import ( - "errors" "fmt" "io" "math/rand" @@ -54,35 +53,38 @@ type ( } ) +var ( + // DefaultProxyConfig is the default Proxy middleware config. + DefaultProxyConfig = ProxyConfig{ + Skipper: DefaultSkipper, + } +) + func proxyHTTP(t *ProxyTarget) http.Handler { return httputil.NewSingleHostReverseProxy(t.URL) } func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - h, ok := w.(http.Hijacker) - if !ok { - c.Error(errors.New("proxy raw, not a hijacker")) - return - } - in, _, err := h.Hijack() + in, _, err := c.Response().Hijack() if err != nil { - c.Error(fmt.Errorf("proxy raw, hijack error=%v, url=%s", r.URL, err)) + c.Error(fmt.Errorf("proxy raw, hijack error=%v, url=%s", t.URL, err)) return } defer in.Close() out, err := net.Dial("tcp", t.URL.Host) if err != nil { - he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", r.URL, err)) + he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", t.URL, err)) c.Error(he) return } defer out.Close() + // Write header err = r.Write(out) if err != nil { - he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request copy error=%v, url=%s", r.URL, err)) + he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request header copy error=%v, url=%s", t.URL, err)) c.Error(he) return } @@ -97,7 +99,7 @@ func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler { go cp(in, out) err = <-errc if err != nil && err != io.EOF { - c.Logger().Errorf("proxy raw, error=%v, url=%s", r.URL, err) + c.Logger().Errorf("proxy raw, copy body error=%v, url=%s", t.URL, err) } }) } @@ -118,8 +120,18 @@ func (r *RoundRobinBalancer) Next() *ProxyTarget { return t } -// Proxy returns an HTTP/WebSocket reverse proxy middleware. -func Proxy(config ProxyConfig) echo.MiddlewareFunc { +// Proxy returns a Proxy middleware. +// +// Proxy middleware forwards the request to upstream server using a configured load balancing technique. +func Proxy(balancer ProxyBalancer) echo.MiddlewareFunc { + c := DefaultProxyConfig + c.Balancer = balancer + return ProxyWithConfig(c) +} + +// ProxyWithConfig returns a Proxy middleware with config. +// See: `Proxy()` +func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc { // Defaults if config.Skipper == nil { config.Skipper = DefaultLoggerConfig.Skipper @@ -130,6 +142,10 @@ func Proxy(config ProxyConfig) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) (err error) { + if config.Skipper(c) { + return next(c) + } + req := c.Request() res := c.Response() tgt := config.Balancer.Next() diff --git a/vendor/github.com/labstack/echo/middleware/recover.go b/vendor/github.com/labstack/echo/middleware/recover.go index 96fa62c9..687a198a 100644 --- a/vendor/github.com/labstack/echo/middleware/recover.go +++ b/vendor/github.com/labstack/echo/middleware/recover.go @@ -5,7 +5,6 @@ import ( "runtime" "github.com/labstack/echo" - "github.com/labstack/gommon/color" ) type ( @@ -64,17 +63,14 @@ func RecoverWithConfig(config RecoverConfig) echo.MiddlewareFunc { defer func() { if r := recover(); r != nil { - var err error - switch r := r.(type) { - case error: - err = r - default: + err, ok := r.(error) + if !ok { err = fmt.Errorf("%v", r) } stack := make([]byte, config.StackSize) length := runtime.Stack(stack, !config.DisableStackAll) if !config.DisablePrintStack { - c.Logger().Printf("[%s] %s %s\n", color.Red("PANIC RECOVER"), err, stack[:length]) + c.Logger().Printf("[PANIC RECOVER] %v %s\n", err, stack[:length]) } c.Error(err) } diff --git a/vendor/github.com/labstack/echo/middleware/static.go b/vendor/github.com/labstack/echo/middleware/static.go index e715c1c4..29686e0c 100644 --- a/vendor/github.com/labstack/echo/middleware/static.go +++ b/vendor/github.com/labstack/echo/middleware/static.go @@ -2,6 +2,7 @@ package middleware import ( "fmt" + "net/http" "os" "path" "path/filepath" @@ -66,7 +67,7 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { } return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { + return func(c echo.Context) (err error) { if config.Skipper(c) { return next(c) } @@ -75,17 +76,25 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { if strings.HasSuffix(c.Path(), "*") { // When serving from a group, e.g. `/static*`. p = c.Param("*") } + p, err = echo.PathUnescape(p) + if err != nil { + return + } name := filepath.Join(config.Root, path.Clean("/"+p)) // "/"+ for security fi, err := os.Stat(name) if err != nil { if os.IsNotExist(err) { - if config.HTML5 && path.Ext(p) == "" { - return c.File(filepath.Join(config.Root, config.Index)) + if err = next(c); err != nil { + if he, ok := err.(*echo.HTTPError); ok { + if config.HTML5 && he.Code == http.StatusNotFound { + return c.File(filepath.Join(config.Root, config.Index)) + } + } + return } - return next(c) } - return err + return } if fi.IsDir() { @@ -99,7 +108,7 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { if os.IsNotExist(err) { return next(c) } - return err + return } return c.File(index) @@ -110,20 +119,20 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { } } -func listDir(name string, res *echo.Response) error { +func listDir(name string, res *echo.Response) (err error) { dir, err := os.Open(name) if err != nil { - return err + return } dirs, err := dir.Readdir(-1) if err != nil { - return err + return } // Create a directory index res.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8) if _, err = fmt.Fprintf(res, "<pre>\n"); err != nil { - return err + return } for _, d := range dirs { name := d.Name() @@ -133,9 +142,9 @@ func listDir(name string, res *echo.Response) error { name += "/" } if _, err = fmt.Fprintf(res, "<a href=\"%s\" style=\"color: %s;\">%s</a>\n", name, color, name); err != nil { - return err + return } } _, err = fmt.Fprintf(res, "</pre>\n") - return err + return } diff --git a/vendor/github.com/labstack/echo/response.go b/vendor/github.com/labstack/echo/response.go index 2c70d213..b23931ae 100644 --- a/vendor/github.com/labstack/echo/response.go +++ b/vendor/github.com/labstack/echo/response.go @@ -11,11 +11,12 @@ type ( // by an HTTP handler to construct an HTTP response. // See: https://golang.org/pkg/net/http/#ResponseWriter Response struct { - Writer http.ResponseWriter - Status int - Size int64 - Committed bool - echo *Echo + echo *Echo + beforeFuncs []func() + Writer http.ResponseWriter + Status int + Size int64 + Committed bool } ) @@ -34,6 +35,11 @@ func (r *Response) Header() http.Header { return r.Writer.Header() } +// Before registers a function which is called just before the response is written. +func (r *Response) Before(fn func()) { + r.beforeFuncs = append(r.beforeFuncs, fn) +} + // WriteHeader sends an HTTP response header with status code. If WriteHeader is // not called explicitly, the first call to Write will trigger an implicit // WriteHeader(http.StatusOK). Thus explicit calls to WriteHeader are mainly @@ -43,6 +49,9 @@ func (r *Response) WriteHeader(code int) { r.echo.Logger.Warn("response already committed") return } + for _, fn := range r.beforeFuncs { + fn() + } r.Status = code r.Writer.WriteHeader(code) r.Committed = true diff --git a/vendor/github.com/labstack/echo/router.go b/vendor/github.com/labstack/echo/router.go index 2ef904e0..626fe225 100644 --- a/vendor/github.com/labstack/echo/router.go +++ b/vendor/github.com/labstack/echo/router.go @@ -394,7 +394,7 @@ func (r *Router) Find(method, path string, c Context) { if cn = cn.findChildByKind(akind); cn == nil { if nn != nil { cn = nn - nn = nil // Next + nn = cn.parent // Next (Issue #954) search = ns if nk == pkind { goto Param diff --git a/vendor/github.com/labstack/echo/util_go17.go b/vendor/github.com/labstack/echo/util_go17.go new file mode 100644 index 00000000..eaae17e3 --- /dev/null +++ b/vendor/github.com/labstack/echo/util_go17.go @@ -0,0 +1,12 @@ +// +build go1.7, !go1.8 + +package echo + +import ( + "net/url" +) + +// PathUnescape is wraps `url.QueryUnescape` +func PathUnescape(s string) (string, error) { + return url.QueryUnescape(s) +} diff --git a/vendor/github.com/labstack/echo/util_go18.go b/vendor/github.com/labstack/echo/util_go18.go new file mode 100644 index 00000000..8a37785b --- /dev/null +++ b/vendor/github.com/labstack/echo/util_go18.go @@ -0,0 +1,10 @@ +// +build go1.8 + +package echo + +import "net/url" + +// PathUnescape is wraps `url.PathUnescape` +func PathUnescape(s string) (string, error) { + return url.PathUnescape(s) +} diff --git a/vendor/manifest b/vendor/manifest index 1423a0b7..78bc2b9a 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -238,7 +238,7 @@ "importpath": "github.com/labstack/echo", "repository": "https://github.com/labstack/echo", "vcs": "git", - "revision": "c3887ebb131d996411cf13a9688ab02c8dba599e", + "revision": "0473c51f1dbd83487effce00702571d19033a6e5", "branch": "master", "notests": true }, |