diff options
Diffstat (limited to 'vendor/github.com')
21 files changed, 364 insertions, 214 deletions
diff --git a/vendor/github.com/labstack/echo/context.go b/vendor/github.com/labstack/echo/context.go index 54fa71ad..39801f00 100644 --- a/vendor/github.com/labstack/echo/context.go +++ b/vendor/github.com/labstack/echo/context.go @@ -274,13 +274,6 @@ func (c *context) Param(name string) string { if n == name { return c.pvalues[i] } - - // Param name with aliases - for _, p := range strings.Split(n, ",") { - if p == name { - return c.pvalues[i] - } - } } } return "" diff --git a/vendor/github.com/labstack/echo/echo.go b/vendor/github.com/labstack/echo/echo.go index 77c238d0..4a54b31a 100644 --- a/vendor/github.com/labstack/echo/echo.go +++ b/vendor/github.com/labstack/echo/echo.go @@ -76,6 +76,7 @@ type ( DisableHTTP2 bool Debug bool HideBanner bool + HidePort bool HTTPErrorHandler HTTPErrorHandler Binder Binder Validator Validator @@ -213,7 +214,7 @@ const ( ) const ( - version = "3.2.5" + version = "3.2.6" website = "https://echo.labstack.com" // http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo banner = ` @@ -414,9 +415,9 @@ func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { // 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) []*Route { - routes := make([]*Route, 0) - for _, m := range methods { - routes = append(routes, e.Add(m, path, handler, middleware...)) + routes := make([]*Route, len(methods)) + for i, m := range methods { + routes[i] = e.Add(m, path, handler, middleware...) } return routes } @@ -424,9 +425,9 @@ func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFun // 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) []*Route { - routes := make([]*Route, 0) - for _, m := range methods { - routes = append(routes, e.Add(m, path, handler, middleware...)) + routes := make([]*Route, len(methods)) + for i, m := range methods { + routes[i] = e.Add(m, path, handler, middleware...) } return routes } @@ -644,7 +645,7 @@ func (e *Echo) StartServer(s *http.Server) (err error) { return err } } - if !e.HideBanner { + if !e.HidePort { e.colorer.Printf("⇨ http server started on %s\n", e.colorer.Green(e.Listener.Addr())) } return s.Serve(e.Listener) @@ -656,7 +657,7 @@ func (e *Echo) StartServer(s *http.Server) (err error) { } e.TLSListener = tls.NewListener(l, s.TLSConfig) } - if !e.HideBanner { + if !e.HidePort { e.colorer.Printf("⇨ https server started on %s\n", e.colorer.Green(e.TLSListener.Addr())) } return s.Serve(e.TLSListener) diff --git a/vendor/github.com/labstack/echo/group.go b/vendor/github.com/labstack/echo/group.go index 6ae32372..f7e61a2e 100644 --- a/vendor/github.com/labstack/echo/group.go +++ b/vendor/github.com/labstack/echo/group.go @@ -20,9 +20,11 @@ func (g *Group) Use(middleware ...MiddlewareFunc) { g.middleware = append(g.middleware, middleware...) // 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 NotFoundHandler(c) - }, g.middleware...) + for _, p := range []string{"", "/*"} { + g.echo.Any(path.Clean(g.prefix+p), func(c Context) error { + return NotFoundHandler(c) + }, g.middleware...) + } } // CONNECT implements `Echo#CONNECT()` for sub-routes within the Group. @@ -71,17 +73,21 @@ func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { } // 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...) +func (g *Group) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route { + routes := make([]*Route, len(methods)) + for i, m := range methods { + routes[i] = g.Add(m, path, handler, middleware...) } + return routes } // 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...) +func (g *Group) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route { + routes := make([]*Route, len(methods)) + for i, m := range methods { + routes[i] = g.Add(m, path, handler, middleware...) } + return routes } // Group creates a new sub-group with prefix and optional sub-group-level middleware. diff --git a/vendor/github.com/labstack/echo/middleware/basic_auth.go b/vendor/github.com/labstack/echo/middleware/basic_auth.go index ae80da95..6d6a37b4 100644 --- a/vendor/github.com/labstack/echo/middleware/basic_auth.go +++ b/vendor/github.com/labstack/echo/middleware/basic_auth.go @@ -88,6 +88,7 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc { } else if valid { return next(c) } + break } } } diff --git a/vendor/github.com/labstack/echo/middleware/body_dump.go b/vendor/github.com/labstack/echo/middleware/body_dump.go index 88b75ee1..14cf33d1 100644 --- a/vendor/github.com/labstack/echo/middleware/body_dump.go +++ b/vendor/github.com/labstack/echo/middleware/body_dump.go @@ -33,7 +33,7 @@ type ( ) var ( - // DefaultBodyDumpConfig is the default Gzip middleware config. + // DefaultBodyDumpConfig is the default BodyDump middleware config. DefaultBodyDumpConfig = BodyDumpConfig{ Skipper: DefaultSkipper, } diff --git a/vendor/github.com/labstack/echo/middleware/body_limit.go b/vendor/github.com/labstack/echo/middleware/body_limit.go index b964cd29..8d8281f4 100644 --- a/vendor/github.com/labstack/echo/middleware/body_limit.go +++ b/vendor/github.com/labstack/echo/middleware/body_limit.go @@ -17,7 +17,7 @@ type ( // Maximum allowed size for a request body, it can be specified // as `4x` or `4xB`, where x is one of the multiple from K, M, G, T or P. - Limit string `json:"limit"` + Limit string `yaml:"limit"` limit int64 } diff --git a/vendor/github.com/labstack/echo/middleware/compress.go b/vendor/github.com/labstack/echo/middleware/compress.go index 1615624c..b876009c 100644 --- a/vendor/github.com/labstack/echo/middleware/compress.go +++ b/vendor/github.com/labstack/echo/middleware/compress.go @@ -20,7 +20,7 @@ type ( // Gzip compression level. // Optional. Default value -1. - Level int `json:"level"` + Level int `yaml:"level"` } gzipResponseWriter struct { diff --git a/vendor/github.com/labstack/echo/middleware/cors.go b/vendor/github.com/labstack/echo/middleware/cors.go index c35fc36c..771000a5 100644 --- a/vendor/github.com/labstack/echo/middleware/cors.go +++ b/vendor/github.com/labstack/echo/middleware/cors.go @@ -16,34 +16,34 @@ type ( // AllowOrigin defines a list of origins that may access the resource. // Optional. Default value []string{"*"}. - AllowOrigins []string `json:"allow_origins"` + AllowOrigins []string `yaml:"allow_origins"` // AllowMethods defines a list methods allowed when accessing the resource. // This is used in response to a preflight request. // Optional. Default value DefaultCORSConfig.AllowMethods. - AllowMethods []string `json:"allow_methods"` + AllowMethods []string `yaml:"allow_methods"` // AllowHeaders defines a list of request headers that can be used when // making the actual request. This in response to a preflight request. // Optional. Default value []string{}. - AllowHeaders []string `json:"allow_headers"` + AllowHeaders []string `yaml:"allow_headers"` // AllowCredentials indicates whether or not the response to the request // can be exposed when the credentials flag is true. When used as part of // a response to a preflight request, this indicates whether or not the // actual request can be made using credentials. // Optional. Default value false. - AllowCredentials bool `json:"allow_credentials"` + AllowCredentials bool `yaml:"allow_credentials"` // ExposeHeaders defines a whitelist headers that clients are allowed to // access. // Optional. Default value []string{}. - ExposeHeaders []string `json:"expose_headers"` + ExposeHeaders []string `yaml:"expose_headers"` // MaxAge indicates how long (in seconds) the results of a preflight request // can be cached. // Optional. Default value 0. - MaxAge int `json:"max_age"` + MaxAge int `yaml:"max_age"` } ) diff --git a/vendor/github.com/labstack/echo/middleware/csrf.go b/vendor/github.com/labstack/echo/middleware/csrf.go index 5bbeecb4..0d2b7fd6 100644 --- a/vendor/github.com/labstack/echo/middleware/csrf.go +++ b/vendor/github.com/labstack/echo/middleware/csrf.go @@ -18,7 +18,7 @@ type ( Skipper Skipper // TokenLength is the length of the generated token. - TokenLength uint8 `json:"token_length"` + TokenLength uint8 `yaml:"token_length"` // Optional. Default value 32. // TokenLookup is a string in the form of "<source>:<key>" that is used @@ -28,35 +28,35 @@ type ( // - "header:<name>" // - "form:<name>" // - "query:<name>" - TokenLookup string `json:"token_lookup"` + TokenLookup string `yaml:"token_lookup"` // Context key to store generated CSRF token into context. // Optional. Default value "csrf". - ContextKey string `json:"context_key"` + ContextKey string `yaml:"context_key"` // Name of the CSRF cookie. This cookie will store CSRF token. // Optional. Default value "csrf". - CookieName string `json:"cookie_name"` + CookieName string `yaml:"cookie_name"` // Domain of the CSRF cookie. // Optional. Default value none. - CookieDomain string `json:"cookie_domain"` + CookieDomain string `yaml:"cookie_domain"` // Path of the CSRF cookie. // Optional. Default value none. - CookiePath string `json:"cookie_path"` + CookiePath string `yaml:"cookie_path"` // Max age (in seconds) of the CSRF cookie. // Optional. Default value 86400 (24hr). - CookieMaxAge int `json:"cookie_max_age"` + CookieMaxAge int `yaml:"cookie_max_age"` // Indicates if CSRF cookie is secure. // Optional. Default value false. - CookieSecure bool `json:"cookie_secure"` + CookieSecure bool `yaml:"cookie_secure"` // Indicates if CSRF cookie is HTTP only. // Optional. Default value false. - CookieHTTPOnly bool `json:"cookie_http_only"` + CookieHTTPOnly bool `yaml:"cookie_http_only"` } // csrfTokenExtractor defines a function that takes `echo.Context` and returns diff --git a/vendor/github.com/labstack/echo/middleware/key_auth.go b/vendor/github.com/labstack/echo/middleware/key_auth.go index 24625260..4990afd9 100644 --- a/vendor/github.com/labstack/echo/middleware/key_auth.go +++ b/vendor/github.com/labstack/echo/middleware/key_auth.go @@ -20,7 +20,8 @@ type ( // Possible values: // - "header:<name>" // - "query:<name>" - KeyLookup string `json:"key_lookup"` + // - "form:<name>" + KeyLookup string `yaml:"key_lookup"` // AuthScheme to be used in the Authorization header. // Optional. Default value "Bearer". @@ -81,6 +82,8 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc { switch parts[0] { case "query": extractor = keyFromQuery(parts[1]) + case "form": + extractor = keyFromForm(parts[1]) } return func(next echo.HandlerFunc) echo.HandlerFunc { @@ -134,3 +137,14 @@ func keyFromQuery(param string) keyExtractor { return key, nil } } + +// keyFromForm returns a `keyExtractor` that extracts key from the form. +func keyFromForm(param string) keyExtractor { + return func(c echo.Context) (string, error) { + key := c.FormValue(param) + if key == "" { + return "", errors.New("Missing key in the form") + } + return key, nil + } +} diff --git a/vendor/github.com/labstack/echo/middleware/logger.go b/vendor/github.com/labstack/echo/middleware/logger.go index b9c54468..c7b80f8c 100644 --- a/vendor/github.com/labstack/echo/middleware/logger.go +++ b/vendor/github.com/labstack/echo/middleware/logger.go @@ -26,6 +26,7 @@ type ( // - time_unix_nano // - time_rfc3339 // - time_rfc3339_nano + // - time_custom // - id (Request ID) // - remote_ip // - uri @@ -46,7 +47,10 @@ type ( // Example "${remote_ip} ${status}" // // Optional. Default value DefaultLoggerConfig.Format. - Format string `json:"format"` + Format string `yaml:"format"` + + // Optional. Default value DefaultLoggerConfig.CustomTimeFormat. + CustomTimeFormat string `yaml:"custom_time_format"` // Output is a writer where logs in JSON format are written. // Optional. Default value os.Stdout. @@ -66,6 +70,7 @@ var ( `"method":"${method}","uri":"${uri}","status":${status}, "latency":${latency},` + `"latency_human":"${latency_human}","bytes_in":${bytes_in},` + `"bytes_out":${bytes_out}}` + "\n", + CustomTimeFormat:"2006-01-02 15:04:05.00000", Output: os.Stdout, colorer: color.New(), } @@ -126,6 +131,8 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc { return buf.WriteString(time.Now().Format(time.RFC3339)) case "time_rfc3339_nano": return buf.WriteString(time.Now().Format(time.RFC3339Nano)) + case "time_custom": + return buf.WriteString(time.Now().Format(config.CustomTimeFormat)) case "id": id := req.Header.Get(echo.HeaderXRequestID) if id == "" { diff --git a/vendor/github.com/labstack/echo/middleware/middleware.go b/vendor/github.com/labstack/echo/middleware/middleware.go index efcbab91..71f95db7 100644 --- a/vendor/github.com/labstack/echo/middleware/middleware.go +++ b/vendor/github.com/labstack/echo/middleware/middleware.go @@ -1,6 +1,12 @@ package middleware -import "github.com/labstack/echo" +import ( + "regexp" + "strconv" + "strings" + + "github.com/labstack/echo" +) type ( // Skipper defines a function to skip middleware. Returning true skips processing @@ -8,6 +14,21 @@ type ( Skipper func(c echo.Context) bool ) +func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer { + groups := pattern.FindAllStringSubmatch(input, -1) + if groups == nil { + return nil + } + values := groups[0][1:] + replace := make([]string, 2*len(values)) + for i, v := range values { + j := 2 * i + replace[j] = "$" + strconv.Itoa(i+1) + replace[j+1] = v + } + return strings.NewReplacer(replace...) +} + // DefaultSkipper returns false which processes the middleware. func DefaultSkipper(echo.Context) bool { return false diff --git a/vendor/github.com/labstack/echo/middleware/proxy.go b/vendor/github.com/labstack/echo/middleware/proxy.go index 4f55f39d..ae3ff527 100644 --- a/vendor/github.com/labstack/echo/middleware/proxy.go +++ b/vendor/github.com/labstack/echo/middleware/proxy.go @@ -8,6 +8,9 @@ import ( "net/http" "net/http/httputil" "net/url" + "regexp" + "strings" + "sync" "sync/atomic" "time" @@ -24,32 +27,48 @@ type ( // Balancer defines a load balancing technique. // Required. - // Possible values: - // - RandomBalancer - // - RoundRobinBalancer Balancer ProxyBalancer + + // Rewrite defines URL path rewrite rules. The values captured in asterisk can be + // retrieved by index e.g. $1, $2 and so on. + // Examples: + // "/old": "/new", + // "/api/*": "/$1", + // "/js/*": "/public/javascripts/$1", + // "/users/*/orders/*": "/user/$1/order/$2", + Rewrite map[string]string + + rewriteRegex map[*regexp.Regexp]string } // ProxyTarget defines the upstream target. ProxyTarget struct { - URL *url.URL + Name string + URL *url.URL } - // RandomBalancer implements a random load balancing technique. - RandomBalancer struct { - Targets []*ProxyTarget - random *rand.Rand + // ProxyBalancer defines an interface to implement a load balancing technique. + ProxyBalancer interface { + AddTarget(*ProxyTarget) bool + RemoveTarget(string) bool + Next() *ProxyTarget } - // RoundRobinBalancer implements a round-robin load balancing technique. - RoundRobinBalancer struct { - Targets []*ProxyTarget - i uint32 + commonBalancer struct { + targets []*ProxyTarget + mutex sync.RWMutex } - // ProxyBalancer defines an interface to implement a load balancing technique. - ProxyBalancer interface { - Next() *ProxyTarget + // RandomBalancer implements a random load balancing technique. + randomBalancer struct { + *commonBalancer + random *rand.Rand + } + + // RoundRobinBalancer implements a round-robin load balancing technique. + roundRobinBalancer struct { + *commonBalancer + i uint32 } ) @@ -104,19 +123,61 @@ func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler { }) } +// NewRandomBalancer returns a random proxy balancer. +func NewRandomBalancer(targets []*ProxyTarget) ProxyBalancer { + b := &randomBalancer{commonBalancer: new(commonBalancer)} + b.targets = targets + return b +} + +// NewRoundRobinBalancer returns a round-robin proxy balancer. +func NewRoundRobinBalancer(targets []*ProxyTarget) ProxyBalancer { + b := &roundRobinBalancer{commonBalancer: new(commonBalancer)} + b.targets = targets + return b +} + +// AddTarget adds an upstream target to the list. +func (b *commonBalancer) AddTarget(target *ProxyTarget) bool { + for _, t := range b.targets { + if t.Name == target.Name { + return false + } + } + b.mutex.Lock() + defer b.mutex.Unlock() + b.targets = append(b.targets, target) + return true +} + +// RemoveTarget removes an upstream target from the list. +func (b *commonBalancer) RemoveTarget(name string) bool { + b.mutex.Lock() + defer b.mutex.Unlock() + for i, t := range b.targets { + if t.Name == name { + b.targets = append(b.targets[:i], b.targets[i+1:]...) + return true + } + } + return false +} + // Next randomly returns an upstream target. -func (r *RandomBalancer) Next() *ProxyTarget { - if r.random == nil { - r.random = rand.New(rand.NewSource(int64(time.Now().Nanosecond()))) +func (b *randomBalancer) Next() *ProxyTarget { + if b.random == nil { + b.random = rand.New(rand.NewSource(int64(time.Now().Nanosecond()))) } - return r.Targets[r.random.Intn(len(r.Targets))] + b.mutex.RLock() + defer b.mutex.RUnlock() + return b.targets[b.random.Intn(len(b.targets))] } // Next returns an upstream target using round-robin technique. -func (r *RoundRobinBalancer) Next() *ProxyTarget { - r.i = r.i % uint32(len(r.Targets)) - t := r.Targets[r.i] - atomic.AddUint32(&r.i, 1) +func (b *roundRobinBalancer) Next() *ProxyTarget { + b.i = b.i % uint32(len(b.targets)) + t := b.targets[b.i] + atomic.AddUint32(&b.i, 1) return t } @@ -139,6 +200,13 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc { if config.Balancer == nil { panic("echo: proxy middleware requires balancer") } + config.rewriteRegex = map[*regexp.Regexp]string{} + + // Initialize + for k, v := range config.Rewrite { + k = strings.Replace(k, "*", "(\\S*)", -1) + config.rewriteRegex[regexp.MustCompile(k)] = v + } return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) (err error) { @@ -150,6 +218,14 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc { res := c.Response() tgt := config.Balancer.Next() + // Rewrite + for k, v := range config.rewriteRegex { + replacer := captureTokens(k, req.URL.Path) + if replacer != nil { + req.URL.Path = replacer.Replace(v) + } + } + // Fix header if req.Header.Get(echo.HeaderXRealIP) == "" { req.Header.Set(echo.HeaderXRealIP, c.RealIP()) diff --git a/vendor/github.com/labstack/echo/middleware/recover.go b/vendor/github.com/labstack/echo/middleware/recover.go index 687a198a..2a42c5b1 100644 --- a/vendor/github.com/labstack/echo/middleware/recover.go +++ b/vendor/github.com/labstack/echo/middleware/recover.go @@ -15,16 +15,16 @@ type ( // Size of the stack to be printed. // Optional. Default value 4KB. - StackSize int `json:"stack_size"` + StackSize int `yaml:"stack_size"` // DisableStackAll disables formatting stack traces of all other goroutines // into buffer after the trace for the current goroutine. // Optional. Default value false. - DisableStackAll bool `json:"disable_stack_all"` + DisableStackAll bool `yaml:"disable_stack_all"` // DisablePrintStack disables printing stack trace. // Optional. Default value as false. - DisablePrintStack bool `json:"disable_print_stack"` + DisablePrintStack bool `yaml:"disable_print_stack"` } ) diff --git a/vendor/github.com/labstack/echo/middleware/redirect.go b/vendor/github.com/labstack/echo/middleware/redirect.go index b87dab09..422263de 100644 --- a/vendor/github.com/labstack/echo/middleware/redirect.go +++ b/vendor/github.com/labstack/echo/middleware/redirect.go @@ -6,29 +6,28 @@ import ( "github.com/labstack/echo" ) -type ( - // RedirectConfig defines the config for Redirect middleware. - RedirectConfig struct { - // Skipper defines a function to skip middleware. - Skipper Skipper - - // Status code to be used when redirecting the request. - // Optional. Default value http.StatusMovedPermanently. - Code int `json:"code"` - } -) +// RedirectConfig defines the config for Redirect middleware. +type RedirectConfig struct { + // Skipper defines a function to skip middleware. + Skipper + + // Status code to be used when redirecting the request. + // Optional. Default value http.StatusMovedPermanently. + Code int `yaml:"code"` +} -const ( - www = "www" -) +// redirectLogic represents a function that given a scheme, host and uri +// can both: 1) determine if redirect is needed (will set ok accordingly) and +// 2) return the appropriate redirect url. +type redirectLogic func(scheme, host, uri string) (ok bool, url string) -var ( - // DefaultRedirectConfig is the default Redirect middleware config. - DefaultRedirectConfig = RedirectConfig{ - Skipper: DefaultSkipper, - Code: http.StatusMovedPermanently, - } -) +const www = "www" + +// DefaultRedirectConfig is the default Redirect middleware config. +var DefaultRedirectConfig = RedirectConfig{ + Skipper: DefaultSkipper, + Code: http.StatusMovedPermanently, +} // HTTPSRedirect redirects http requests to https. // For example, http://labstack.com will be redirect to https://labstack.com. @@ -41,29 +40,12 @@ func HTTPSRedirect() echo.MiddlewareFunc { // HTTPSRedirectWithConfig returns an HTTPSRedirect middleware with config. // See `HTTPSRedirect()`. func HTTPSRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { - // Defaults - if config.Skipper == nil { - config.Skipper = DefaultTrailingSlashConfig.Skipper - } - if config.Code == 0 { - config.Code = DefaultRedirectConfig.Code - } - - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - if config.Skipper(c) { - return next(c) - } - - req := c.Request() - host := req.Host - uri := req.RequestURI - if !c.IsTLS() { - return c.Redirect(config.Code, "https://"+host+uri) - } - return next(c) + return redirect(config, func(scheme, host, uri string) (ok bool, url string) { + if ok = scheme != "https"; ok { + url = "https://" + host + uri } - } + return + }) } // HTTPSWWWRedirect redirects http requests to https www. @@ -77,29 +59,12 @@ func HTTPSWWWRedirect() echo.MiddlewareFunc { // HTTPSWWWRedirectWithConfig returns an HTTPSRedirect middleware with config. // See `HTTPSWWWRedirect()`. func HTTPSWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { - // Defaults - if config.Skipper == nil { - config.Skipper = DefaultTrailingSlashConfig.Skipper - } - if config.Code == 0 { - config.Code = DefaultRedirectConfig.Code - } - - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - if config.Skipper(c) { - return next(c) - } - - req := c.Request() - host := req.Host - uri := req.RequestURI - if !c.IsTLS() && host[:3] != www { - return c.Redirect(config.Code, "https://www."+host+uri) - } - return next(c) + return redirect(config, func(scheme, host, uri string) (ok bool, url string) { + if ok = scheme != "https" && host[:3] != www; ok { + url = "https://www." + host + uri } - } + return + }) } // HTTPSNonWWWRedirect redirects http requests to https non www. @@ -113,32 +78,15 @@ func HTTPSNonWWWRedirect() echo.MiddlewareFunc { // HTTPSNonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config. // See `HTTPSNonWWWRedirect()`. func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { - // Defaults - if config.Skipper == nil { - config.Skipper = DefaultTrailingSlashConfig.Skipper - } - if config.Code == 0 { - config.Code = DefaultRedirectConfig.Code - } - - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - if config.Skipper(c) { - return next(c) - } - - req := c.Request() - host := req.Host - uri := req.RequestURI - if !c.IsTLS() { - if host[:3] == www { - return c.Redirect(config.Code, "https://"+host[4:]+uri) - } - return c.Redirect(config.Code, "https://"+host+uri) + return redirect(config, func(scheme, host, uri string) (ok bool, url string) { + if ok = scheme != "https"; ok { + if host[:3] == www { + host = host[4:] } - return next(c) + url = "https://" + host + uri } - } + return + }) } // WWWRedirect redirects non www requests to www. @@ -152,30 +100,12 @@ func WWWRedirect() echo.MiddlewareFunc { // WWWRedirectWithConfig returns an HTTPSRedirect middleware with config. // See `WWWRedirect()`. func WWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { - // Defaults - if config.Skipper == nil { - config.Skipper = DefaultTrailingSlashConfig.Skipper - } - if config.Code == 0 { - config.Code = DefaultRedirectConfig.Code - } - - return func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - if config.Skipper(c) { - return next(c) - } - - req := c.Request() - scheme := c.Scheme() - host := req.Host - if host[:3] != www { - uri := req.RequestURI - return c.Redirect(config.Code, scheme+"://www."+host+uri) - } - return next(c) + return redirect(config, func(scheme, host, uri string) (ok bool, url string) { + if ok = host[:3] != www; ok { + url = scheme + "://www." + host + uri } - } + return + }) } // NonWWWRedirect redirects www requests to non www. @@ -189,6 +119,15 @@ func NonWWWRedirect() echo.MiddlewareFunc { // NonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config. // 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 { + url = scheme + "://" + host[4:] + uri + } + return + }) +} + +func redirect(config RedirectConfig, cb redirectLogic) echo.MiddlewareFunc { if config.Skipper == nil { config.Skipper = DefaultTrailingSlashConfig.Skipper } @@ -202,13 +141,12 @@ func NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { return next(c) } - req := c.Request() - scheme := c.Scheme() + req, scheme := c.Request(), c.Scheme() host := req.Host - if host[:3] == www { - uri := req.RequestURI - return c.Redirect(config.Code, scheme+"://"+host[4:]+uri) + if ok, url := cb(scheme, host, req.RequestURI); ok { + return c.Redirect(config.Code, url) } + return next(c) } } diff --git a/vendor/github.com/labstack/echo/middleware/rewrite.go b/vendor/github.com/labstack/echo/middleware/rewrite.go new file mode 100644 index 00000000..60a59bec --- /dev/null +++ b/vendor/github.com/labstack/echo/middleware/rewrite.go @@ -0,0 +1,83 @@ +package middleware + +import ( + "regexp" + "strings" + + "github.com/labstack/echo" +) + +type ( + // RewriteConfig defines the config for Rewrite middleware. + RewriteConfig struct { + // Skipper defines a function to skip middleware. + Skipper Skipper + + // Rules defines the URL path rewrite rules. The values captured in asterisk can be + // retrieved by index e.g. $1, $2 and so on. + // Example: + // "/old": "/new", + // "/api/*": "/$1", + // "/js/*": "/public/javascripts/$1", + // "/users/*/orders/*": "/user/$1/order/$2", + // Required. + Rules map[string]string `yaml:"rules"` + + rulesRegex map[*regexp.Regexp]string + } +) + +var ( + // DefaultRewriteConfig is the default Rewrite middleware config. + DefaultRewriteConfig = RewriteConfig{ + Skipper: DefaultSkipper, + } +) + +// Rewrite returns a Rewrite middleware. +// +// Rewrite middleware rewrites the URL path based on the provided rules. +func Rewrite(rules map[string]string) echo.MiddlewareFunc { + c := DefaultRewriteConfig + c.Rules = rules + return RewriteWithConfig(c) +} + +// RewriteWithConfig returns a Rewrite middleware with config. +// See: `Rewrite()`. +func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc { + // Defaults + if config.Rules == nil { + panic("echo: rewrite middleware requires url path rewrite rules") + } + if config.Skipper == nil { + config.Skipper = DefaultBodyDumpConfig.Skipper + } + config.rulesRegex = map[*regexp.Regexp]string{} + + // Initialize + for k, v := range config.Rules { + k = strings.Replace(k, "*", "(\\S*)", -1) + config.rulesRegex[regexp.MustCompile(k)] = v + } + + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) (err error) { + if config.Skipper(c) { + return next(c) + } + + req := c.Request() + + // Rewrite + for k, v := range config.rulesRegex { + replacer := captureTokens(k, req.URL.Path) + if replacer != nil { + req.URL.Path = replacer.Replace(v) + } + } + + return next(c) + } + } +} diff --git a/vendor/github.com/labstack/echo/middleware/secure.go b/vendor/github.com/labstack/echo/middleware/secure.go index 0125e74a..188c0c40 100644 --- a/vendor/github.com/labstack/echo/middleware/secure.go +++ b/vendor/github.com/labstack/echo/middleware/secure.go @@ -15,12 +15,12 @@ type ( // XSSProtection provides protection against cross-site scripting attack (XSS) // by setting the `X-XSS-Protection` header. // Optional. Default value "1; mode=block". - XSSProtection string `json:"xss_protection"` + XSSProtection string `yaml:"xss_protection"` // ContentTypeNosniff provides protection against overriding Content-Type // header by setting the `X-Content-Type-Options` header. // Optional. Default value "nosniff". - ContentTypeNosniff string `json:"content_type_nosniff"` + ContentTypeNosniff string `yaml:"content_type_nosniff"` // XFrameOptions can be used to indicate whether or not a browser should // be allowed to render a page in a <frame>, <iframe> or <object> . @@ -32,27 +32,27 @@ type ( // - "SAMEORIGIN" - The page can only be displayed in a frame on the same origin as the page itself. // - "DENY" - The page cannot be displayed in a frame, regardless of the site attempting to do so. // - "ALLOW-FROM uri" - The page can only be displayed in a frame on the specified origin. - XFrameOptions string `json:"x_frame_options"` + XFrameOptions string `yaml:"x_frame_options"` // HSTSMaxAge sets the `Strict-Transport-Security` header to indicate how // long (in seconds) browsers should remember that this site is only to // be accessed using HTTPS. This reduces your exposure to some SSL-stripping // man-in-the-middle (MITM) attacks. // Optional. Default value 0. - HSTSMaxAge int `json:"hsts_max_age"` + HSTSMaxAge int `yaml:"hsts_max_age"` // HSTSExcludeSubdomains won't include subdomains tag in the `Strict Transport Security` // header, excluding all subdomains from security policy. It has no effect // unless HSTSMaxAge is set to a non-zero value. // Optional. Default value false. - HSTSExcludeSubdomains bool `json:"hsts_exclude_subdomains"` + HSTSExcludeSubdomains bool `yaml:"hsts_exclude_subdomains"` // ContentSecurityPolicy sets the `Content-Security-Policy` header providing // security against cross-site scripting (XSS), clickjacking and other code // injection attacks resulting from execution of malicious content in the // trusted web page context. // Optional. Default value "". - ContentSecurityPolicy string `json:"content_security_policy"` + ContentSecurityPolicy string `yaml:"content_security_policy"` } ) diff --git a/vendor/github.com/labstack/echo/middleware/slash.go b/vendor/github.com/labstack/echo/middleware/slash.go index 1114d722..9af56caf 100644 --- a/vendor/github.com/labstack/echo/middleware/slash.go +++ b/vendor/github.com/labstack/echo/middleware/slash.go @@ -12,7 +12,7 @@ type ( // Status code to be used when redirecting the request. // Optional, but when provided the request is redirected using this code. - RedirectCode int `json:"redirect_code"` + RedirectCode int `yaml:"redirect_code"` } ) diff --git a/vendor/github.com/labstack/echo/middleware/static.go b/vendor/github.com/labstack/echo/middleware/static.go index 29686e0c..7208c3a2 100644 --- a/vendor/github.com/labstack/echo/middleware/static.go +++ b/vendor/github.com/labstack/echo/middleware/static.go @@ -19,20 +19,20 @@ type ( // Root directory from where the static content is served. // Required. - Root string `json:"root"` + Root string `yaml:"root"` // Index file for serving a directory. // Optional. Default value "index.html". - Index string `json:"index"` + Index string `yaml:"index"` // Enable HTML5 mode by forwarding all not-found requests to root so that // SPA (single-page application) can handle the routing. // Optional. Default value false. - HTML5 bool `json:"html5"` + HTML5 bool `yaml:"html5"` // Enable directory browsing. // Optional. Default value false. - Browse bool `json:"browse"` + Browse bool `yaml:"browse"` } ) diff --git a/vendor/github.com/labstack/echo/response.go b/vendor/github.com/labstack/echo/response.go index b23931ae..93204098 100644 --- a/vendor/github.com/labstack/echo/response.go +++ b/vendor/github.com/labstack/echo/response.go @@ -4,6 +4,7 @@ import ( "bufio" "net" "net/http" + "strconv" ) type ( @@ -11,12 +12,14 @@ type ( // by an HTTP handler to construct an HTTP response. // See: https://golang.org/pkg/net/http/#ResponseWriter Response struct { - echo *Echo - beforeFuncs []func() - Writer http.ResponseWriter - Status int - Size int64 - Committed bool + echo *Echo + contentLength int64 + beforeFuncs []func() + afterFuncs []func() + Writer http.ResponseWriter + Status int + Size int64 + Committed bool } ) @@ -40,6 +43,12 @@ func (r *Response) Before(fn func()) { r.beforeFuncs = append(r.beforeFuncs, fn) } +// After registers a function which is called just after the response is written. +// If the `Content-Length` is unknown, none of the after function is executed. +func (r *Response) After(fn func()) { + r.afterFuncs = append(r.afterFuncs, 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 @@ -55,6 +64,7 @@ func (r *Response) WriteHeader(code int) { r.Status = code r.Writer.WriteHeader(code) r.Committed = true + r.contentLength, _ = strconv.ParseInt(r.Header().Get(HeaderContentLength), 10, 0) } // Write writes the data to the connection as part of an HTTP reply. @@ -64,6 +74,11 @@ func (r *Response) Write(b []byte) (n int, err error) { } n, err = r.Writer.Write(b) r.Size += int64(n) + if r.Size == r.contentLength { + for _, fn := range r.afterFuncs { + fn() + } + } return } @@ -91,6 +106,9 @@ func (r *Response) CloseNotify() <-chan bool { } func (r *Response) reset(w http.ResponseWriter) { + r.contentLength = 0 + r.beforeFuncs = nil + r.afterFuncs = nil r.Writer = w r.Size = 0 r.Status = http.StatusOK diff --git a/vendor/github.com/labstack/echo/router.go b/vendor/github.com/labstack/echo/router.go index 626fe225..3af4be0b 100644 --- a/vendor/github.com/labstack/echo/router.go +++ b/vendor/github.com/labstack/echo/router.go @@ -1,7 +1,5 @@ package echo -import "strings" - type ( // Router is the registry of all registered routes for an `Echo` instance for // request matching and URL path parameter parsing. @@ -175,12 +173,6 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string if len(cn.pnames) == 0 { // Issue #729 cn.pnames = pnames } - for i, n := range pnames { - // Param name aliases - if i < len(cn.pnames) && !strings.Contains(cn.pnames[i], n) { - cn.pnames[i] += "," + n - } - } } } return |