summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/labstack/echo/v4/middleware
diff options
context:
space:
mode:
authorWim <wim@42.be>2021-10-17 00:47:22 +0200
committerGitHub <noreply@github.com>2021-10-17 00:47:22 +0200
commit4dd8bae5c91fa4aef09d865d8fef1acd84f90925 (patch)
treeffad9b242daccaf8c86d1c1fbd59032302bd3be9 /vendor/github.com/labstack/echo/v4/middleware
parent7ae45c42e712bd0e66c101f3f714c05aa1dc2104 (diff)
downloadmatterbridge-msglm-4dd8bae5c91fa4aef09d865d8fef1acd84f90925.tar.gz
matterbridge-msglm-4dd8bae5c91fa4aef09d865d8fef1acd84f90925.tar.bz2
matterbridge-msglm-4dd8bae5c91fa4aef09d865d8fef1acd84f90925.zip
Update dependencies (#1610)
* Update dependencies * Update module to go 1.17
Diffstat (limited to 'vendor/github.com/labstack/echo/v4/middleware')
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/jwt.go8
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/key_auth.go15
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/request_logger.go314
-rw-r--r--vendor/github.com/labstack/echo/v4/middleware/timeout.go60
4 files changed, 391 insertions, 6 deletions
diff --git a/vendor/github.com/labstack/echo/v4/middleware/jwt.go b/vendor/github.com/labstack/echo/v4/middleware/jwt.go
index bce47874..21e33ab8 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/jwt.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/jwt.go
@@ -1,3 +1,5 @@
+// +build go1.15
+
package middleware
import (
@@ -7,7 +9,7 @@ import (
"reflect"
"strings"
- "github.com/dgrijalva/jwt-go"
+ "github.com/golang-jwt/jwt"
"github.com/labstack/echo/v4"
)
@@ -88,7 +90,7 @@ type (
// 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
+ // Defaults to implementation using `github.com/golang-jwt/jwt` as JWT implementation library
ParseTokenFunc func(auth string, c echo.Context) (interface{}, error)
}
@@ -293,7 +295,7 @@ func jwtFromHeader(header string, authScheme string) jwtExtractor {
return func(c echo.Context) (string, error) {
auth := c.Request().Header.Get(header)
l := len(authScheme)
- if len(auth) > l+1 && auth[:l] == authScheme {
+ if len(auth) > l+1 && strings.EqualFold(auth[:l], authScheme) {
return auth[l+1:], nil
}
return "", ErrJWTMissing
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 fd169aa2..54f3b47f 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/key_auth.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/key_auth.go
@@ -2,6 +2,7 @@ package middleware
import (
"errors"
+ "fmt"
"net/http"
"strings"
@@ -21,6 +22,7 @@ type (
// - "header:<name>"
// - "query:<name>"
// - "form:<name>"
+ // - "cookie:<name>"
KeyLookup string `yaml:"key_lookup"`
// AuthScheme to be used in the Authorization header.
@@ -91,6 +93,8 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
extractor = keyFromQuery(parts[1])
case "form":
extractor = keyFromForm(parts[1])
+ case "cookie":
+ extractor = keyFromCookie(parts[1])
}
return func(next echo.HandlerFunc) echo.HandlerFunc {
@@ -164,3 +168,14 @@ func keyFromForm(param string) keyExtractor {
return key, nil
}
}
+
+// keyFromCookie returns a `keyExtractor` that extracts key from the form.
+func keyFromCookie(cookieName string) keyExtractor {
+ return func(c echo.Context) (string, error) {
+ key, err := c.Cookie(cookieName)
+ if err != nil {
+ return "", fmt.Errorf("missing key in cookies: %w", err)
+ }
+ return key.Value, nil
+ }
+}
diff --git a/vendor/github.com/labstack/echo/v4/middleware/request_logger.go b/vendor/github.com/labstack/echo/v4/middleware/request_logger.go
new file mode 100644
index 00000000..1b3e3eaa
--- /dev/null
+++ b/vendor/github.com/labstack/echo/v4/middleware/request_logger.go
@@ -0,0 +1,314 @@
+package middleware
+
+import (
+ "errors"
+ "github.com/labstack/echo/v4"
+ "net/http"
+ "time"
+)
+
+// Example for `fmt.Printf`
+// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
+// LogStatus: true,
+// LogURI: true,
+// LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
+// fmt.Printf("REQUEST: uri: %v, status: %v\n", v.URI, v.Status)
+// return nil
+// },
+// }))
+//
+// Example for Zerolog (https://github.com/rs/zerolog)
+// logger := zerolog.New(os.Stdout)
+// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
+// LogURI: true,
+// LogStatus: true,
+// LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
+// logger.Info().
+// Str("URI", v.URI).
+// Int("status", v.Status).
+// Msg("request")
+//
+// return nil
+// },
+// }))
+//
+// Example for Zap (https://github.com/uber-go/zap)
+// logger, _ := zap.NewProduction()
+// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
+// LogURI: true,
+// LogStatus: true,
+// LogValuesFunc: func(c echo.Context, v middleware.RequestLoggerValues) error {
+// logger.Info("request",
+// zap.String("URI", v.URI),
+// zap.Int("status", v.Status),
+// )
+//
+// return nil
+// },
+// }))
+//
+// Example for Logrus (https://github.com/sirupsen/logrus)
+// log := logrus.New()
+// e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
+// LogURI: true,
+// LogStatus: true,
+// LogValuesFunc: func(c echo.Context, values middleware.RequestLoggerValues) error {
+// log.WithFields(logrus.Fields{
+// "URI": values.URI,
+// "status": values.Status,
+// }).Info("request")
+//
+// return nil
+// },
+// }))
+
+// RequestLoggerConfig is configuration for Request Logger middleware.
+type RequestLoggerConfig struct {
+ // Skipper defines a function to skip middleware.
+ Skipper Skipper
+
+ // BeforeNextFunc defines a function that is called before next middleware or handler is called in chain.
+ BeforeNextFunc func(c echo.Context)
+ // LogValuesFunc defines a function that is called with values extracted by logger from request/response.
+ // Mandatory.
+ LogValuesFunc func(c echo.Context, v RequestLoggerValues) error
+
+ // LogLatency instructs logger to record duration it took to execute rest of the handler chain (next(c) call).
+ LogLatency bool
+ // LogProtocol instructs logger to extract request protocol (i.e. `HTTP/1.1` or `HTTP/2`)
+ LogProtocol bool
+ // LogRemoteIP instructs logger to extract request remote IP. See `echo.Context.RealIP()` for implementation details.
+ LogRemoteIP bool
+ // LogHost instructs logger to extract request host value (i.e. `example.com`)
+ LogHost bool
+ // LogMethod instructs logger to extract request method value (i.e. `GET` etc)
+ LogMethod bool
+ // LogURI instructs logger to extract request URI (i.e. `/list?lang=en&page=1`)
+ LogURI bool
+ // LogURIPath instructs logger to extract request URI path part (i.e. `/list`)
+ LogURIPath bool
+ // LogRoutePath instructs logger to extract route path part to which request was matched to (i.e. `/user/:id`)
+ LogRoutePath bool
+ // LogRequestID instructs logger to extract request ID from request `X-Request-ID` header or response if request did not have value.
+ LogRequestID bool
+ // LogReferer instructs logger to extract request referer values.
+ LogReferer bool
+ // LogUserAgent instructs logger to extract request user agent values.
+ LogUserAgent bool
+ // LogStatus instructs logger to extract response status code. If handler chain returns an echo.HTTPError,
+ // the status code is extracted from the echo.HTTPError returned
+ LogStatus bool
+ // LogError instructs logger to extract error returned from executed handler chain.
+ LogError bool
+ // LogContentLength instructs logger to extract content length header value. Note: this value could be different from
+ // actual request body size as it could be spoofed etc.
+ LogContentLength bool
+ // LogResponseSize instructs logger to extract response content length value. Note: when used with Gzip middleware
+ // this value may not be always correct.
+ LogResponseSize bool
+ // LogHeaders instructs logger to extract given list of headers from request. Note: request can contain more than
+ // one header with same value so slice of values is been logger for each given header.
+ //
+ // Note: header values are converted to canonical form with http.CanonicalHeaderKey as this how request parser converts header
+ // names to. For example, the canonical key for "accept-encoding" is "Accept-Encoding".
+ LogHeaders []string
+ // LogQueryParams instructs logger to extract given list of query parameters from request URI. Note: request can
+ // contain more than one query parameter with same name so slice of values is been logger for each given query param name.
+ LogQueryParams []string
+ // LogFormValues instructs logger to extract given list of form values from request body+URI. Note: request can
+ // contain more than one form value with same name so slice of values is been logger for each given form value name.
+ LogFormValues []string
+
+ timeNow func() time.Time
+}
+
+// RequestLoggerValues contains extracted values from logger.
+type RequestLoggerValues struct {
+ // StartTime is time recorded before next middleware/handler is executed.
+ StartTime time.Time
+ // Latency is duration it took to execute rest of the handler chain (next(c) call).
+ Latency time.Duration
+ // Protocol is request protocol (i.e. `HTTP/1.1` or `HTTP/2`)
+ Protocol string
+ // RemoteIP is request remote IP. See `echo.Context.RealIP()` for implementation details.
+ RemoteIP string
+ // Host is request host value (i.e. `example.com`)
+ Host string
+ // Method is request method value (i.e. `GET` etc)
+ Method string
+ // URI is request URI (i.e. `/list?lang=en&page=1`)
+ URI string
+ // URIPath is request URI path part (i.e. `/list`)
+ URIPath string
+ // RoutePath is route path part to which request was matched to (i.e. `/user/:id`)
+ RoutePath string
+ // RequestID is request ID from request `X-Request-ID` header or response if request did not have value.
+ RequestID string
+ // Referer is request referer values.
+ Referer string
+ // UserAgent is request user agent values.
+ UserAgent string
+ // Status is response status code. Then handler returns an echo.HTTPError then code from there.
+ Status int
+ // Error is error returned from executed handler chain.
+ Error error
+ // ContentLength is content length header value. Note: this value could be different from actual request body size
+ // as it could be spoofed etc.
+ ContentLength string
+ // ResponseSize is response content length value. Note: when used with Gzip middleware this value may not be always correct.
+ ResponseSize int64
+ // Headers are list of headers from request. Note: request can contain more than one header with same value so slice
+ // of values is been logger for each given header.
+ // Note: header values are converted to canonical form with http.CanonicalHeaderKey as this how request parser converts header
+ // names to. For example, the canonical key for "accept-encoding" is "Accept-Encoding".
+ Headers map[string][]string
+ // QueryParams are list of query parameters from request URI. Note: request can contain more than one query parameter
+ // with same name so slice of values is been logger for each given query param name.
+ QueryParams map[string][]string
+ // FormValues are list of form values from request body+URI. Note: request can contain more than one form value with
+ // same name so slice of values is been logger for each given form value name.
+ FormValues map[string][]string
+}
+
+// RequestLoggerWithConfig returns a RequestLogger middleware with config.
+func RequestLoggerWithConfig(config RequestLoggerConfig) echo.MiddlewareFunc {
+ mw, err := config.ToMiddleware()
+ if err != nil {
+ panic(err)
+ }
+ return mw
+}
+
+// ToMiddleware converts RequestLoggerConfig into middleware or returns an error for invalid configuration.
+func (config RequestLoggerConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
+ if config.Skipper == nil {
+ config.Skipper = DefaultSkipper
+ }
+ now = time.Now
+ if config.timeNow != nil {
+ now = config.timeNow
+ }
+
+ if config.LogValuesFunc == nil {
+ return nil, errors.New("missing LogValuesFunc callback function for request logger middleware")
+ }
+
+ logHeaders := len(config.LogHeaders) > 0
+ headers := append([]string(nil), config.LogHeaders...)
+ for i, v := range headers {
+ headers[i] = http.CanonicalHeaderKey(v)
+ }
+
+ logQueryParams := len(config.LogQueryParams) > 0
+ logFormValues := len(config.LogFormValues) > 0
+
+ return func(next echo.HandlerFunc) echo.HandlerFunc {
+ return func(c echo.Context) error {
+ if config.Skipper(c) {
+ return next(c)
+ }
+
+ req := c.Request()
+ res := c.Response()
+ start := now()
+
+ if config.BeforeNextFunc != nil {
+ config.BeforeNextFunc(c)
+ }
+ err := next(c)
+
+ v := RequestLoggerValues{
+ StartTime: start,
+ }
+ if config.LogLatency {
+ v.Latency = now().Sub(start)
+ }
+ if config.LogProtocol {
+ v.Protocol = req.Proto
+ }
+ if config.LogRemoteIP {
+ v.RemoteIP = c.RealIP()
+ }
+ if config.LogHost {
+ v.Host = req.Host
+ }
+ if config.LogMethod {
+ v.Method = req.Method
+ }
+ if config.LogURI {
+ v.URI = req.RequestURI
+ }
+ if config.LogURIPath {
+ p := req.URL.Path
+ if p == "" {
+ p = "/"
+ }
+ v.URIPath = p
+ }
+ if config.LogRoutePath {
+ v.RoutePath = c.Path()
+ }
+ if config.LogRequestID {
+ id := req.Header.Get(echo.HeaderXRequestID)
+ if id == "" {
+ id = res.Header().Get(echo.HeaderXRequestID)
+ }
+ v.RequestID = id
+ }
+ if config.LogReferer {
+ v.Referer = req.Referer()
+ }
+ if config.LogUserAgent {
+ v.UserAgent = req.UserAgent()
+ }
+ if config.LogStatus {
+ v.Status = res.Status
+ if err != nil {
+ if httpErr, ok := err.(*echo.HTTPError); ok {
+ v.Status = httpErr.Code
+ }
+ }
+ }
+ if config.LogError && err != nil {
+ v.Error = err
+ }
+ if config.LogContentLength {
+ v.ContentLength = req.Header.Get(echo.HeaderContentLength)
+ }
+ if config.LogResponseSize {
+ v.ResponseSize = res.Size
+ }
+ if logHeaders {
+ v.Headers = map[string][]string{}
+ for _, header := range headers {
+ if values, ok := req.Header[header]; ok {
+ v.Headers[header] = values
+ }
+ }
+ }
+ if logQueryParams {
+ queryParams := c.QueryParams()
+ v.QueryParams = map[string][]string{}
+ for _, param := range config.LogQueryParams {
+ if values, ok := queryParams[param]; ok {
+ v.QueryParams[param] = values
+ }
+ }
+ }
+ if logFormValues {
+ v.FormValues = map[string][]string{}
+ for _, formValue := range config.LogFormValues {
+ if values, ok := req.Form[formValue]; ok {
+ v.FormValues[formValue] = values
+ }
+ }
+ }
+
+ if errOnLog := config.LogValuesFunc(c, v); errOnLog != nil {
+ return errOnLog
+ }
+
+ return err
+ }
+ }, nil
+}
diff --git a/vendor/github.com/labstack/echo/v4/middleware/timeout.go b/vendor/github.com/labstack/echo/v4/middleware/timeout.go
index 73113654..768ef8d7 100644
--- a/vendor/github.com/labstack/echo/v4/middleware/timeout.go
+++ b/vendor/github.com/labstack/echo/v4/middleware/timeout.go
@@ -8,6 +8,53 @@ import (
"github.com/labstack/echo/v4"
)
+// ---------------------------------------------------------------------------------------------------------------
+// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+// WARNING: Timeout middleware causes more problems than it solves.
+// WARNING: This middleware should be first middleware as it messes with request Writer and could cause data race if
+// it is in other position
+//
+// Depending on out requirements you could be better of setting timeout to context and
+// check its deadline from handler.
+//
+// For example: create middleware to set timeout to context
+// func RequestTimeout(timeout time.Duration) echo.MiddlewareFunc {
+// return func(next echo.HandlerFunc) echo.HandlerFunc {
+// return func(c echo.Context) error {
+// timeoutCtx, cancel := context.WithTimeout(c.Request().Context(), timeout)
+// c.SetRequest(c.Request().WithContext(timeoutCtx))
+// defer cancel()
+// return next(c)
+// }
+// }
+//}
+//
+// Create handler that checks for context deadline and runs actual task in separate coroutine
+// Note: separate coroutine may not be even if you do not want to process continue executing and
+// just want to stop long-running handler to stop and you are using "context aware" methods (ala db queries with ctx)
+// e.GET("/", func(c echo.Context) error {
+//
+// doneCh := make(chan error)
+// go func(ctx context.Context) {
+// doneCh <- myPossiblyLongRunningBackgroundTaskWithCtx(ctx)
+// }(c.Request().Context())
+//
+// select { // wait for task to finish or context to timeout/cancelled
+// case err := <-doneCh:
+// if err != nil {
+// return err
+// }
+// return c.String(http.StatusOK, "OK")
+// case <-c.Request().Context().Done():
+// if c.Request().Context().Err() == context.DeadlineExceeded {
+// return c.String(http.StatusServiceUnavailable, "timeout")
+// }
+// return c.Request().Context().Err()
+// }
+//
+// })
+//
+
type (
// TimeoutConfig defines the config for Timeout middleware.
TimeoutConfig struct {
@@ -116,13 +163,20 @@ func (t echoHandlerFuncWrapper) ServeHTTP(rw http.ResponseWriter, r *http.Reques
// we restore original writer only for cases we did not timeout. On timeout we have already sent response to client
// and should not anymore send additional headers/data
// so on timeout writer stays what http.TimeoutHandler uses and prevents writing headers/body
- t.ctx.Response().Writer = originalWriter
if err != nil {
- // call global error handler to write error to the client. This is needed or `http.TimeoutHandler` will send status code by itself
- // and after that our tries to write status code will not work anymore
+ // Error must be written into Writer created in `http.TimeoutHandler` so to get Response into `commited` state.
+ // So call global error handler to write error to the client. This is needed or `http.TimeoutHandler` will send
+ // status code by itself and after that our tries to write status code will not work anymore and/or create errors in
+ // log about `superfluous response.WriteHeader call from`
t.ctx.Error(err)
// we pass error from handler to middlewares up in handler chain to act on it if needed. But this means that
// global error handler is probably be called twice as `t.ctx.Error` already does that.
+
+ // NB: later call of the global error handler or middlewares will not take any effect, as echo.Response will be
+ // already marked as `committed` because we called global error handler above.
+ t.ctx.Response().Writer = originalWriter // make sure we restore before we signal original coroutine about the error
t.errChan <- err
+ return
}
+ t.ctx.Response().Writer = originalWriter
}