summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/labstack/echo
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/labstack/echo')
-rw-r--r--vendor/github.com/labstack/echo/v4/CHANGELOG.md15
-rw-r--r--vendor/github.com/labstack/echo/v4/bind.go23
-rw-r--r--vendor/github.com/labstack/echo/v4/context.go20
-rw-r--r--vendor/github.com/labstack/echo/v4/echo.go10
-rw-r--r--vendor/github.com/labstack/echo/v4/json.go31
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/jwt.go53
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go3
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/request_id.go6
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/timeout.go7
9 files changed, 131 insertions, 37 deletions
diff --git a/vendor/github.com/labstack/echo/v4/CHANGELOG.md b/vendor/github.com/labstack/echo/v4/CHANGELOG.md
index f4a74760..892d7095 100644
--- a/vendor/github.com/labstack/echo/v4/CHANGELOG.md
+++ b/vendor/github.com/labstack/echo/v4/CHANGELOG.md
@@ -1,5 +1,20 @@
# Changelog
+## v4.4.0 - 2021-07-12
+
+**Fixes**
+
+* Split HeaderXForwardedFor header only by comma [#1878](https://github.com/labstack/echo/pull/1878)
+* Fix Timeout middleware Context propagation [#1910](https://github.com/labstack/echo/pull/1910)
+
+**Enhancements**
+
+* Bind data using headers as source [#1866](https://github.com/labstack/echo/pull/1866)
+* Adds JWTConfig.ParseTokenFunc to JWT middleware to allow different libraries implementing JWT parsing. [#1887](https://github.com/labstack/echo/pull/1887)
+* Adding tests for Echo#Host [#1895](https://github.com/labstack/echo/pull/1895)
+* Adds RequestIDHandler function to RequestID middleware [#1898](https://github.com/labstack/echo/pull/1898)
+* Allow for custom JSON encoding implementations [#1880](https://github.com/labstack/echo/pull/1880)
+
## v4.3.0 - 2021-05-08
**Important notes**
diff --git a/vendor/github.com/labstack/echo/v4/bind.go b/vendor/github.com/labstack/echo/v4/bind.go
index dfdf82d0..fdf0524c 100644
--- a/vendor/github.com/labstack/echo/v4/bind.go
+++ b/vendor/github.com/labstack/echo/v4/bind.go
@@ -2,7 +2,6 @@ package echo
import (
"encoding"
- "encoding/json"
"encoding/xml"
"errors"
"fmt"
@@ -66,13 +65,13 @@ func (b *DefaultBinder) BindBody(c Context, i interface{}) (err error) {
ctype := req.Header.Get(HeaderContentType)
switch {
case strings.HasPrefix(ctype, MIMEApplicationJSON):
- if err = json.NewDecoder(req.Body).Decode(i); err != nil {
- if ute, ok := err.(*json.UnmarshalTypeError); ok {
- return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, field=%v, offset=%v", ute.Type, ute.Value, ute.Field, ute.Offset)).SetInternal(err)
- } else if se, ok := err.(*json.SyntaxError); ok {
- return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Syntax error: offset=%v, error=%v", se.Offset, se.Error())).SetInternal(err)
+ if err = c.Echo().JSONSerializer.Deserialize(c, i); err != nil {
+ switch err.(type) {
+ case *HTTPError:
+ return err
+ default:
+ return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
}
- return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
}
case strings.HasPrefix(ctype, MIMEApplicationXML), strings.HasPrefix(ctype, MIMETextXML):
if err = xml.NewDecoder(req.Body).Decode(i); err != nil {
@@ -97,6 +96,14 @@ func (b *DefaultBinder) BindBody(c Context, i interface{}) (err error) {
return nil
}
+// BindHeaders binds HTTP headers to a bindable object
+func (b *DefaultBinder) BindHeaders(c Context, i interface{}) error {
+ if err := b.bindData(i, c.Request().Header, "header"); err != nil {
+ return NewHTTPError(http.StatusBadRequest, err.Error()).SetInternal(err)
+ }
+ return nil
+}
+
// Bind implements the `Binder#Bind` function.
// Binding is done in following order: 1) path params; 2) query params; 3) request body. Each step COULD override previous
// step binded values. For single source binding use their own methods BindBody, BindQueryParams, BindPathParams.
@@ -134,7 +141,7 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
// !struct
if typ.Kind() != reflect.Struct {
- if tag == "param" || tag == "query" {
+ if tag == "param" || tag == "query" || tag == "header" {
// incompatible type, data is probably to be found in the body
return nil
}
diff --git a/vendor/github.com/labstack/echo/v4/context.go b/vendor/github.com/labstack/echo/v4/context.go
index 0cee48ce..91ab6e48 100644
--- a/vendor/github.com/labstack/echo/v4/context.go
+++ b/vendor/github.com/labstack/echo/v4/context.go
@@ -2,7 +2,6 @@ package echo
import (
"bytes"
- "encoding/json"
"encoding/xml"
"fmt"
"io"
@@ -276,9 +275,9 @@ func (c *context) RealIP() string {
}
// Fall back to legacy behavior
if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" {
- i := strings.IndexAny(ip, ", ")
+ i := strings.IndexAny(ip, ",")
if i > 0 {
- return ip[:i]
+ return strings.TrimSpace(ip[:i])
}
return ip
}
@@ -457,17 +456,16 @@ func (c *context) String(code int, s string) (err error) {
}
func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error) {
- enc := json.NewEncoder(c.response)
- _, pretty := c.QueryParams()["pretty"]
- if c.echo.Debug || pretty {
- enc.SetIndent("", " ")
+ indent := ""
+ if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
+ indent = defaultIndent
}
c.writeContentType(MIMEApplicationJavaScriptCharsetUTF8)
c.response.WriteHeader(code)
if _, err = c.response.Write([]byte(callback + "(")); err != nil {
return
}
- if err = enc.Encode(i); err != nil {
+ if err = c.echo.JSONSerializer.Serialize(c, i, indent); err != nil {
return
}
if _, err = c.response.Write([]byte(");")); err != nil {
@@ -477,13 +475,9 @@ func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error
}
func (c *context) json(code int, i interface{}, indent string) error {
- enc := json.NewEncoder(c.response)
- if indent != "" {
- enc.SetIndent("", indent)
- }
c.writeContentType(MIMEApplicationJSONCharsetUTF8)
c.response.Status = code
- return enc.Encode(i)
+ return c.echo.JSONSerializer.Serialize(c, i, indent)
}
func (c *context) JSON(code int, i interface{}) (err error) {
diff --git a/vendor/github.com/labstack/echo/v4/echo.go b/vendor/github.com/labstack/echo/v4/echo.go
index dd0cbf35..406e806b 100644
--- a/vendor/github.com/labstack/echo/v4/echo.go
+++ b/vendor/github.com/labstack/echo/v4/echo.go
@@ -90,6 +90,7 @@ type (
HidePort bool
HTTPErrorHandler HTTPErrorHandler
Binder Binder
+ JSONSerializer JSONSerializer
Validator Validator
Renderer Renderer
Logger Logger
@@ -125,6 +126,12 @@ type (
Validate(i interface{}) error
}
+ // JSONSerializer is the interface that encodes and decodes JSON to and from interfaces.
+ JSONSerializer interface {
+ Serialize(c Context, i interface{}, indent string) error
+ Deserialize(c Context, i interface{}) error
+ }
+
// Renderer is the interface that wraps the Render function.
Renderer interface {
Render(io.Writer, string, interface{}, Context) error
@@ -234,7 +241,7 @@ const (
const (
// Version of Echo
- Version = "4.3.0"
+ Version = "4.4.0"
website = "https://echo.labstack.com"
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
banner = `
@@ -315,6 +322,7 @@ func New() (e *Echo) {
e.TLSServer.Handler = e
e.HTTPErrorHandler = e.DefaultHTTPErrorHandler
e.Binder = &DefaultBinder{}
+ e.JSONSerializer = &DefaultJSONSerializer{}
e.Logger.SetLevel(log.ERROR)
e.StdLogger = stdLog.New(e.Logger.Output(), e.Logger.Prefix()+": ", 0)
e.pool.New = func() interface{} {
diff --git a/vendor/github.com/labstack/echo/v4/json.go b/vendor/github.com/labstack/echo/v4/json.go
new file mode 100644
index 00000000..16b2d057
--- /dev/null
+++ b/vendor/github.com/labstack/echo/v4/json.go
@@ -0,0 +1,31 @@
+package echo
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+)
+
+// DefaultJSONSerializer implements JSON encoding using encoding/json.
+type DefaultJSONSerializer struct{}
+
+// Serialize converts an interface into a json and writes it to the response.
+// You can optionally use the indent parameter to produce pretty JSONs.
+func (d DefaultJSONSerializer) Serialize(c Context, i interface{}, indent string) error {
+ enc := json.NewEncoder(c.Response())
+ if indent != "" {
+ enc.SetIndent("", indent)
+ }
+ return enc.Encode(i)
+}
+
+// Deserialize reads a JSON from a request body and converts it into an interface.
+func (d DefaultJSONSerializer) Deserialize(c Context, i interface{}) error {
+ err := json.NewDecoder(c.Request().Body).Decode(i)
+ if ute, ok := err.(*json.UnmarshalTypeError); ok {
+ return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, field=%v, offset=%v", ute.Type, ute.Value, ute.Field, ute.Offset)).SetInternal(err)
+ } else if se, ok := err.(*json.SyntaxError); ok {
+ return NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Syntax error: offset=%v, error=%v", se.Offset, se.Error())).SetInternal(err)
+ }
+ return err
+}
diff --git a/vendor/github.com/labstack/echo/v4/middleware/jwt.go b/vendor/github.com/labstack/echo/v4/middleware/jwt.go
index cd35b621..bce47874 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/jwt.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/jwt.go
@@ -1,6 +1,7 @@
package middleware
import (
+ "errors"
"fmt"
"net/http"
"reflect"
@@ -49,11 +50,12 @@ type (
// Optional. Default value "user".
ContextKey string
- // Claims are extendable claims data defining token content.
+ // Claims are extendable claims data defining token content. Used by default ParseTokenFunc implementation.
+ // Not used if custom ParseTokenFunc is set.
// Optional. Default value jwt.MapClaims
Claims jwt.Claims
- // TokenLookup is a string in the form of "<source>:<name>" that is used
+ // TokenLookup is a string in the form of "<source>:<name>" or "<source>:<name>,<source>:<name>" that is used
// to extract token from the request.
// Optional. Default value "header:Authorization".
// Possible values:
@@ -62,6 +64,9 @@ type (
// - "param:<name>"
// - "cookie:<name>"
// - "form:<name>"
+ // Multiply sources example:
+ // - "header: Authorization,cookie: myowncookie"
+
TokenLookup string
// AuthScheme to be used in the Authorization header.
@@ -71,13 +76,20 @@ type (
// KeyFunc defines a user-defined function that supplies the public key for a token validation.
// The function shall take care of verifying the signing algorithm and selecting the proper key.
// A user-defined KeyFunc can be useful if tokens are issued by an external party.
+ // Used by default ParseTokenFunc implementation.
//
// When a user-defined KeyFunc is provided, SigningKey, SigningKeys, and SigningMethod are ignored.
// This is one of the three options to provide a token validation key.
// The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
// Required if neither SigningKeys nor SigningKey is provided.
+ // Not used if custom ParseTokenFunc is set.
// Default to an internal implementation verifying the signing algorithm and selecting the proper key.
KeyFunc jwt.Keyfunc
+
+ // ParseTokenFunc defines a user-defined function that parses token from given auth. Returns an error when token
+ // parsing fails or parsed token is invalid.
+ // Defaults to implementation using `github.com/dgrijalva/jwt-go` as JWT implementation library
+ ParseTokenFunc func(auth string, c echo.Context) (interface{}, error)
}
// JWTSuccessHandler defines a function which is executed for a valid token.
@@ -137,7 +149,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
if config.Skipper == nil {
config.Skipper = DefaultJWTConfig.Skipper
}
- if config.SigningKey == nil && len(config.SigningKeys) == 0 && config.KeyFunc == nil {
+ if config.SigningKey == nil && len(config.SigningKeys) == 0 && config.KeyFunc == nil && config.ParseTokenFunc == nil {
panic("echo: jwt middleware requires signing key")
}
if config.SigningMethod == "" {
@@ -158,6 +170,9 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
if config.KeyFunc == nil {
config.KeyFunc = config.defaultKeyFunc
}
+ if config.ParseTokenFunc == nil {
+ config.ParseTokenFunc = config.defaultParseToken
+ }
// Initialize
// Split sources
@@ -211,16 +226,8 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
return err
}
- token := new(jwt.Token)
- // Issue #647, #656
- if _, ok := config.Claims.(jwt.MapClaims); ok {
- token, err = jwt.Parse(auth, config.KeyFunc)
- } else {
- 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 {
+ token, err := config.ParseTokenFunc(auth, c)
+ if err == nil {
// Store user information from token into context.
c.Set(config.ContextKey, token)
if config.SuccessHandler != nil {
@@ -243,6 +250,26 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
}
}
+func (config *JWTConfig) defaultParseToken(auth string, c echo.Context) (interface{}, error) {
+ token := new(jwt.Token)
+ var err error
+ // Issue #647, #656
+ if _, ok := config.Claims.(jwt.MapClaims); ok {
+ token, err = jwt.Parse(auth, config.KeyFunc)
+ } else {
+ 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 {
+ return nil, err
+ }
+ if !token.Valid {
+ return nil, errors.New("invalid token")
+ }
+ return token, nil
+}
+
// defaultKeyFunc returns a signing key of the given token.
func (config *JWTConfig) defaultKeyFunc(t *jwt.Token) (interface{}, error) {
// Check the signing method
diff --git a/vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go b/vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
index 46a310d9..0291eb45 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/rate_limiter.go
@@ -169,7 +169,8 @@ type (
/*
NewRateLimiterMemoryStore returns an instance of RateLimiterMemoryStore with
-the provided rate (as req/s). Burst and ExpiresIn will be set to default values.
+the provided rate (as req/s). The provided rate less than 1 will be treated as zero.
+Burst and ExpiresIn will be set to default values.
Example (with 20 requests/sec):
diff --git a/vendor/github.com/labstack/echo/v4/middleware/request_id.go b/vendor/github.com/labstack/echo/v4/middleware/request_id.go
index 21f801f3..b0baeeb2 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/request_id.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/request_id.go
@@ -14,6 +14,9 @@ type (
// Generator defines a function to generate an ID.
// Optional. Default value random.String(32).
Generator func() string
+
+ // RequestIDHandler defines a function which is executed for a request id.
+ RequestIDHandler func(echo.Context, string)
}
)
@@ -53,6 +56,9 @@ func RequestIDWithConfig(config RequestIDConfig) echo.MiddlewareFunc {
rid = config.Generator()
}
res.Header().Set(echo.HeaderXRequestID, rid)
+ if config.RequestIDHandler != nil {
+ config.RequestIDHandler(c, rid)
+ }
return next(c)
}
diff --git a/vendor/github.com/labstack/echo/v4/middleware/timeout.go b/vendor/github.com/labstack/echo/v4/middleware/timeout.go
index fb8ae421..73113654 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/timeout.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/timeout.go
@@ -2,9 +2,10 @@ package middleware
import (
"context"
- "github.com/labstack/echo/v4"
"net/http"
"time"
+
+ "github.com/labstack/echo/v4"
)
type (
@@ -87,6 +88,10 @@ type echoHandlerFuncWrapper struct {
}
func (t echoHandlerFuncWrapper) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ // replace echo.Context Request with the one provided by TimeoutHandler to let later middlewares/handler on the chain
+ // handle properly it's cancellation
+ t.ctx.SetRequest(r)
+
// replace writer with TimeoutHandler custom one. This will guarantee that
// `writes by h to its ResponseWriter will return ErrHandlerTimeout.`
originalWriter := t.ctx.Response().Writer