mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-07-04 08:57:44 +00:00
Update vendor (#1498)
This commit is contained in:
30
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
30
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
@ -1,6 +1,30 @@
|
||||
# Changelog
|
||||
|
||||
## v4.2.2 - 2020-04-07
|
||||
## v4.3.0 - 2021-05-08
|
||||
|
||||
**Important notes**
|
||||
|
||||
* Route matching has improvements for following cases:
|
||||
1. Correctly match routes with parameter part as last part of route (with trailing backslash)
|
||||
2. Considering handlers when resolving routes and search for matching http method handler
|
||||
* Echo minimal Go version is now 1.13.
|
||||
|
||||
**Fixes**
|
||||
|
||||
* When url ends with slash first param route is the match [#1804](https://github.com/labstack/echo/pull/1812)
|
||||
* Router should check if node is suitable as matching route by path+method and if not then continue search in tree [#1808](https://github.com/labstack/echo/issues/1808)
|
||||
* Fix timeout middleware not writing response correctly when handler panics [#1864](https://github.com/labstack/echo/pull/1864)
|
||||
* Fix binder not working with embedded pointer structs [#1861](https://github.com/labstack/echo/pull/1861)
|
||||
* Add Go 1.16 to CI and drop 1.12 specific code [#1850](https://github.com/labstack/echo/pull/1850)
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Make KeyFunc public in JWT middleware [#1756](https://github.com/labstack/echo/pull/1756)
|
||||
* Add support for optional filesystem to the static middleware [#1797](https://github.com/labstack/echo/pull/1797)
|
||||
* Add a custom error handler to key-auth middleware [#1847](https://github.com/labstack/echo/pull/1847)
|
||||
* Allow JWT token to be looked up from multiple sources [#1845](https://github.com/labstack/echo/pull/1845)
|
||||
|
||||
## v4.2.2 - 2021-04-07
|
||||
|
||||
**Fixes**
|
||||
|
||||
@ -10,7 +34,7 @@
|
||||
* Fix panic in redirect middleware on short host name (#1813)
|
||||
* Fix timeout middleware docs (#1836)
|
||||
|
||||
## v4.2.1 - 2020-03-08
|
||||
## v4.2.1 - 2021-03-08
|
||||
|
||||
**Important notes**
|
||||
|
||||
@ -32,7 +56,7 @@ A performance regression has been fixed, even bringing better performance than b
|
||||
This release was made possible by our **contributors**:
|
||||
aldas, clwluvw, lammel, Le0tk0k, maciej-jezierski, rkilingr, stffabi, withshubh
|
||||
|
||||
## v4.2.0 - 2020-02-11
|
||||
## v4.2.0 - 2021-02-11
|
||||
|
||||
**Important notes**
|
||||
|
||||
|
2
vendor/github.com/labstack/echo/v4/LICENSE
generated
vendored
2
vendor/github.com/labstack/echo/v4/LICENSE
generated
vendored
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 LabStack
|
||||
Copyright (c) 2021 LabStack
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
9
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
9
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
@ -144,11 +144,20 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
typeField := typ.Field(i)
|
||||
structField := val.Field(i)
|
||||
if typeField.Anonymous {
|
||||
if structField.Kind() == reflect.Ptr {
|
||||
structField = structField.Elem()
|
||||
}
|
||||
}
|
||||
if !structField.CanSet() {
|
||||
continue
|
||||
}
|
||||
structFieldKind := structField.Kind()
|
||||
inputFieldName := typeField.Tag.Get(tag)
|
||||
if typeField.Anonymous && structField.Kind() == reflect.Struct && inputFieldName != "" {
|
||||
// if anonymous struct with query/param/form tags, report an error
|
||||
return errors.New("query/param/form tags are not allowed with anonymous struct field")
|
||||
}
|
||||
|
||||
if inputFieldName == "" {
|
||||
// If tag is nil, we inspect if the field is a not BindUnmarshaler struct and try to bind data into it (might contains fields with tags).
|
||||
|
2
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
2
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
@ -234,7 +234,7 @@ const (
|
||||
|
||||
const (
|
||||
// Version of Echo
|
||||
Version = "4.2.2"
|
||||
Version = "4.3.0"
|
||||
website = "https://echo.labstack.com"
|
||||
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
||||
banner = `
|
||||
|
10
vendor/github.com/labstack/echo/v4/go.mod
generated
vendored
10
vendor/github.com/labstack/echo/v4/go.mod
generated
vendored
@ -5,12 +5,12 @@ go 1.15
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/labstack/gommon v0.3.0
|
||||
github.com/mattn/go-colorable v0.1.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/valyala/fasttemplate v1.2.1
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 // indirect
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
|
||||
)
|
||||
|
36
vendor/github.com/labstack/echo/v4/go.sum
generated
vendored
36
vendor/github.com/labstack/echo/v4/go.sum
generated
vendored
@ -4,12 +4,10 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
@ -20,32 +18,26 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirSiguP9Q/veMtkYyf0o8=
|
||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
2
vendor/github.com/labstack/echo/v4/middleware/csrf.go
generated
vendored
2
vendor/github.com/labstack/echo/v4/middleware/csrf.go
generated
vendored
@ -110,7 +110,7 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFunc {
|
||||
if config.CookieMaxAge == 0 {
|
||||
config.CookieMaxAge = DefaultCSRFConfig.CookieMaxAge
|
||||
}
|
||||
if config.CookieSameSite == SameSiteNoneMode {
|
||||
if config.CookieSameSite == http.SameSiteNoneMode {
|
||||
config.CookieSecure = true
|
||||
}
|
||||
|
||||
|
12
vendor/github.com/labstack/echo/v4/middleware/csrf_samesite.go
generated
vendored
12
vendor/github.com/labstack/echo/v4/middleware/csrf_samesite.go
generated
vendored
@ -1,12 +0,0 @@
|
||||
// +build go1.13
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
// SameSiteNoneMode required to be redefined for Go 1.12 support (see #1524)
|
||||
SameSiteNoneMode http.SameSite = http.SameSiteNoneMode
|
||||
)
|
12
vendor/github.com/labstack/echo/v4/middleware/csrf_samesite_1.12.go
generated
vendored
12
vendor/github.com/labstack/echo/v4/middleware/csrf_samesite_1.12.go
generated
vendored
@ -1,12 +0,0 @@
|
||||
// +build !go1.13
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
// SameSiteNoneMode required to be redefined for Go 1.12 support (see #1524)
|
||||
SameSiteNoneMode http.SameSite = 4
|
||||
)
|
108
vendor/github.com/labstack/echo/v4/middleware/jwt.go
generated
vendored
108
vendor/github.com/labstack/echo/v4/middleware/jwt.go
generated
vendored
@ -29,15 +29,19 @@ type (
|
||||
// ErrorHandlerWithContext is almost identical to ErrorHandler, but it's passed the current context.
|
||||
ErrorHandlerWithContext JWTErrorHandlerWithContext
|
||||
|
||||
// Signing key to validate token. Used as fallback if SigningKeys has length 0.
|
||||
// Required. This or SigningKeys.
|
||||
// Signing key to validate token.
|
||||
// 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 user-defined KeyFunc nor SigningKeys is provided.
|
||||
SigningKey interface{}
|
||||
|
||||
// Map of signing keys to validate token with kid field usage.
|
||||
// Required. This or SigningKey.
|
||||
// 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 user-defined KeyFunc nor SigningKey is provided.
|
||||
SigningKeys map[string]interface{}
|
||||
|
||||
// Signing method, used to check token signing method.
|
||||
// Signing method used to check the token's signing algorithm.
|
||||
// Optional. Default value HS256.
|
||||
SigningMethod string
|
||||
|
||||
@ -64,7 +68,16 @@ type (
|
||||
// Optional. Default value "Bearer".
|
||||
AuthScheme string
|
||||
|
||||
keyFunc jwt.Keyfunc
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
// Default to an internal implementation verifying the signing algorithm and selecting the proper key.
|
||||
KeyFunc jwt.Keyfunc
|
||||
}
|
||||
|
||||
// JWTSuccessHandler defines a function which is executed for a valid token.
|
||||
@ -99,6 +112,7 @@ var (
|
||||
TokenLookup: "header:" + echo.HeaderAuthorization,
|
||||
AuthScheme: "Bearer",
|
||||
Claims: jwt.MapClaims{},
|
||||
KeyFunc: nil,
|
||||
}
|
||||
)
|
||||
|
||||
@ -123,7 +137,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
||||
if config.Skipper == nil {
|
||||
config.Skipper = DefaultJWTConfig.Skipper
|
||||
}
|
||||
if config.SigningKey == nil && len(config.SigningKeys) == 0 {
|
||||
if config.SigningKey == nil && len(config.SigningKeys) == 0 && config.KeyFunc == nil {
|
||||
panic("echo: jwt middleware requires signing key")
|
||||
}
|
||||
if config.SigningMethod == "" {
|
||||
@ -141,35 +155,29 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
||||
if config.AuthScheme == "" {
|
||||
config.AuthScheme = DefaultJWTConfig.AuthScheme
|
||||
}
|
||||
config.keyFunc = func(t *jwt.Token) (interface{}, error) {
|
||||
// Check the signing method
|
||||
if t.Method.Alg() != config.SigningMethod {
|
||||
return nil, fmt.Errorf("unexpected jwt signing method=%v", t.Header["alg"])
|
||||
}
|
||||
if len(config.SigningKeys) > 0 {
|
||||
if kid, ok := t.Header["kid"].(string); ok {
|
||||
if key, ok := config.SigningKeys[kid]; ok {
|
||||
return key, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected jwt key id=%v", t.Header["kid"])
|
||||
}
|
||||
|
||||
return config.SigningKey, nil
|
||||
if config.KeyFunc == nil {
|
||||
config.KeyFunc = config.defaultKeyFunc
|
||||
}
|
||||
|
||||
// Initialize
|
||||
parts := strings.Split(config.TokenLookup, ":")
|
||||
extractor := jwtFromHeader(parts[1], config.AuthScheme)
|
||||
switch parts[0] {
|
||||
case "query":
|
||||
extractor = jwtFromQuery(parts[1])
|
||||
case "param":
|
||||
extractor = jwtFromParam(parts[1])
|
||||
case "cookie":
|
||||
extractor = jwtFromCookie(parts[1])
|
||||
case "form":
|
||||
extractor = jwtFromForm(parts[1])
|
||||
// Split sources
|
||||
sources := strings.Split(config.TokenLookup, ",")
|
||||
var extractors []jwtExtractor
|
||||
for _, source := range sources {
|
||||
parts := strings.Split(source, ":")
|
||||
|
||||
switch parts[0] {
|
||||
case "query":
|
||||
extractors = append(extractors, jwtFromQuery(parts[1]))
|
||||
case "param":
|
||||
extractors = append(extractors, jwtFromParam(parts[1]))
|
||||
case "cookie":
|
||||
extractors = append(extractors, jwtFromCookie(parts[1]))
|
||||
case "form":
|
||||
extractors = append(extractors, jwtFromForm(parts[1]))
|
||||
case "header":
|
||||
extractors = append(extractors, jwtFromHeader(parts[1], config.AuthScheme))
|
||||
}
|
||||
}
|
||||
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
@ -181,8 +189,17 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
||||
if config.BeforeFunc != nil {
|
||||
config.BeforeFunc(c)
|
||||
}
|
||||
|
||||
auth, err := extractor(c)
|
||||
var auth string
|
||||
var err error
|
||||
for _, extractor := range extractors {
|
||||
// Extract token from extractor, if it's not fail break the loop and
|
||||
// set auth
|
||||
auth, err = extractor(c)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
// If none of extractor has a token, handle error
|
||||
if err != nil {
|
||||
if config.ErrorHandler != nil {
|
||||
return config.ErrorHandler(err)
|
||||
@ -193,14 +210,15 @@ 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)
|
||||
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)
|
||||
token, err = jwt.ParseWithClaims(auth, claims, config.KeyFunc)
|
||||
}
|
||||
if err == nil && token.Valid {
|
||||
// Store user information from token into context.
|
||||
@ -225,6 +243,24 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// defaultKeyFunc returns a signing key of the given token.
|
||||
func (config *JWTConfig) defaultKeyFunc(t *jwt.Token) (interface{}, error) {
|
||||
// Check the signing method
|
||||
if t.Method.Alg() != config.SigningMethod {
|
||||
return nil, fmt.Errorf("unexpected jwt signing method=%v", t.Header["alg"])
|
||||
}
|
||||
if len(config.SigningKeys) > 0 {
|
||||
if kid, ok := t.Header["kid"].(string); ok {
|
||||
if key, ok := config.SigningKeys[kid]; ok {
|
||||
return key, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected jwt key id=%v", t.Header["kid"])
|
||||
}
|
||||
|
||||
return config.SigningKey, nil
|
||||
}
|
||||
|
||||
// jwtFromHeader returns a `jwtExtractor` that extracts token from the request header.
|
||||
func jwtFromHeader(header string, authScheme string) jwtExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
|
13
vendor/github.com/labstack/echo/v4/middleware/key_auth.go
generated
vendored
13
vendor/github.com/labstack/echo/v4/middleware/key_auth.go
generated
vendored
@ -30,12 +30,19 @@ type (
|
||||
// Validator is a function to validate key.
|
||||
// Required.
|
||||
Validator KeyAuthValidator
|
||||
|
||||
// ErrorHandler defines a function which is executed for an invalid key.
|
||||
// It may be used to define a custom error.
|
||||
ErrorHandler KeyAuthErrorHandler
|
||||
}
|
||||
|
||||
// KeyAuthValidator defines a function to validate KeyAuth credentials.
|
||||
KeyAuthValidator func(string, echo.Context) (bool, error)
|
||||
|
||||
keyExtractor func(echo.Context) (string, error)
|
||||
|
||||
// KeyAuthErrorHandler defines a function which is executed for an invalid key.
|
||||
KeyAuthErrorHandler func(error, echo.Context) error
|
||||
)
|
||||
|
||||
var (
|
||||
@ -95,10 +102,16 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc {
|
||||
// Extract and verify key
|
||||
key, err := extractor(c)
|
||||
if err != nil {
|
||||
if config.ErrorHandler != nil {
|
||||
return config.ErrorHandler(err, c)
|
||||
}
|
||||
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
valid, err := config.Validator(key, c)
|
||||
if err != nil {
|
||||
if config.ErrorHandler != nil {
|
||||
return config.ErrorHandler(err, c)
|
||||
}
|
||||
return &echo.HTTPError{
|
||||
Code: http.StatusUnauthorized,
|
||||
Message: "invalid key",
|
||||
|
37
vendor/github.com/labstack/echo/v4/middleware/proxy.go
generated
vendored
37
vendor/github.com/labstack/echo/v4/middleware/proxy.go
generated
vendored
@ -1,13 +1,16 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@ -264,3 +267,37 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StatusCodeContextCanceled is a custom HTTP status code for situations
|
||||
// where a client unexpectedly closed the connection to the server.
|
||||
// As there is no standard error code for "client closed connection", but
|
||||
// various well-known HTTP clients and server implement this HTTP code we use
|
||||
// 499 too instead of the more problematic 5xx, which does not allow to detect this situation
|
||||
const StatusCodeContextCanceled = 499
|
||||
|
||||
func proxyHTTP(tgt *ProxyTarget, c echo.Context, config ProxyConfig) http.Handler {
|
||||
proxy := httputil.NewSingleHostReverseProxy(tgt.URL)
|
||||
proxy.ErrorHandler = func(resp http.ResponseWriter, req *http.Request, err error) {
|
||||
desc := tgt.URL.String()
|
||||
if tgt.Name != "" {
|
||||
desc = fmt.Sprintf("%s(%s)", tgt.Name, tgt.URL.String())
|
||||
}
|
||||
// If the client canceled the request (usually by closing the connection), we can report a
|
||||
// client error (4xx) instead of a server error (5xx) to correctly identify the situation.
|
||||
// The Go standard library (at of late 2020) wraps the exported, standard
|
||||
// context.Canceled error with unexported garbage value requiring a substring check, see
|
||||
// https://github.com/golang/go/blob/6965b01ea248cabb70c3749fd218b36089a21efb/src/net/net.go#L416-L430
|
||||
if err == context.Canceled || strings.Contains(err.Error(), "operation was canceled") {
|
||||
httpError := echo.NewHTTPError(StatusCodeContextCanceled, fmt.Sprintf("client closed connection: %v", err))
|
||||
httpError.Internal = err
|
||||
c.Set("_error", httpError)
|
||||
} else {
|
||||
httpError := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("remote %s unreachable, could not forward: %v", desc, err))
|
||||
httpError.Internal = err
|
||||
c.Set("_error", httpError)
|
||||
}
|
||||
}
|
||||
proxy.Transport = config.Transport
|
||||
proxy.ModifyResponse = config.ModifyResponse
|
||||
return proxy
|
||||
}
|
||||
|
47
vendor/github.com/labstack/echo/v4/middleware/proxy_1_11.go
generated
vendored
47
vendor/github.com/labstack/echo/v4/middleware/proxy_1_11.go
generated
vendored
@ -1,47 +0,0 @@
|
||||
// +build go1.11
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// StatusCodeContextCanceled is a custom HTTP status code for situations
|
||||
// where a client unexpectedly closed the connection to the server.
|
||||
// As there is no standard error code for "client closed connection", but
|
||||
// various well-known HTTP clients and server implement this HTTP code we use
|
||||
// 499 too instead of the more problematic 5xx, which does not allow to detect this situation
|
||||
const StatusCodeContextCanceled = 499
|
||||
|
||||
func proxyHTTP(tgt *ProxyTarget, c echo.Context, config ProxyConfig) http.Handler {
|
||||
proxy := httputil.NewSingleHostReverseProxy(tgt.URL)
|
||||
proxy.ErrorHandler = func(resp http.ResponseWriter, req *http.Request, err error) {
|
||||
desc := tgt.URL.String()
|
||||
if tgt.Name != "" {
|
||||
desc = fmt.Sprintf("%s(%s)", tgt.Name, tgt.URL.String())
|
||||
}
|
||||
// If the client canceled the request (usually by closing the connection), we can report a
|
||||
// client error (4xx) instead of a server error (5xx) to correctly identify the situation.
|
||||
// The Go standard library (at of late 2020) wraps the exported, standard
|
||||
// context.Canceled error with unexported garbage value requiring a substring check, see
|
||||
// https://github.com/golang/go/blob/6965b01ea248cabb70c3749fd218b36089a21efb/src/net/net.go#L416-L430
|
||||
if err == context.Canceled || strings.Contains(err.Error(), "operation was canceled") {
|
||||
httpError := echo.NewHTTPError(StatusCodeContextCanceled, fmt.Sprintf("client closed connection: %v", err))
|
||||
httpError.Internal = err
|
||||
c.Set("_error", httpError)
|
||||
} else {
|
||||
httpError := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("remote %s unreachable, could not forward: %v", desc, err))
|
||||
httpError.Internal = err
|
||||
c.Set("_error", httpError)
|
||||
}
|
||||
}
|
||||
proxy.Transport = config.Transport
|
||||
proxy.ModifyResponse = config.ModifyResponse
|
||||
return proxy
|
||||
}
|
14
vendor/github.com/labstack/echo/v4/middleware/proxy_1_11_n.go
generated
vendored
14
vendor/github.com/labstack/echo/v4/middleware/proxy_1_11_n.go
generated
vendored
@ -1,14 +0,0 @@
|
||||
// +build !go1.11
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func proxyHTTP(t *ProxyTarget, c echo.Context, config ProxyConfig) http.Handler {
|
||||
return httputil.NewSingleHostReverseProxy(t.URL)
|
||||
}
|
80
vendor/github.com/labstack/echo/v4/middleware/static.go
generated
vendored
80
vendor/github.com/labstack/echo/v4/middleware/static.go
generated
vendored
@ -42,6 +42,10 @@ type (
|
||||
// the filesystem path is not doubled
|
||||
// Optional. Default value false.
|
||||
IgnoreBase bool `yaml:"ignoreBase"`
|
||||
|
||||
// Filesystem provides access to the static content.
|
||||
// Optional. Defaults to http.Dir(config.Root)
|
||||
Filesystem http.FileSystem `yaml:"-"`
|
||||
}
|
||||
)
|
||||
|
||||
@ -146,6 +150,10 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc {
|
||||
if config.Index == "" {
|
||||
config.Index = DefaultStaticConfig.Index
|
||||
}
|
||||
if config.Filesystem == nil {
|
||||
config.Filesystem = http.Dir(config.Root)
|
||||
config.Root = "."
|
||||
}
|
||||
|
||||
// Index template
|
||||
t, err := template.New("index").Parse(html)
|
||||
@ -178,49 +186,73 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc {
|
||||
}
|
||||
}
|
||||
|
||||
fi, err := os.Stat(name)
|
||||
file, err := openFile(config.Filesystem, name)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
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
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = next(c); err == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
he, ok := err.(*echo.HTTPError)
|
||||
if !(ok && config.HTML5 && he.Code == http.StatusNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err = openFile(config.Filesystem, filepath.Join(config.Root, config.Index))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
index := filepath.Join(name, config.Index)
|
||||
fi, err = os.Stat(index)
|
||||
defer file.Close()
|
||||
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
index, err := openFile(config.Filesystem, filepath.Join(name, config.Index))
|
||||
if err != nil {
|
||||
if config.Browse {
|
||||
return listDir(t, name, c.Response())
|
||||
return listDir(t, name, file, c.Response())
|
||||
}
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
return next(c)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
return c.File(index)
|
||||
defer index.Close()
|
||||
|
||||
info, err = index.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return serveFile(c, index, info)
|
||||
}
|
||||
|
||||
return c.File(name)
|
||||
return serveFile(c, file, info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func listDir(t *template.Template, name string, res *echo.Response) (err error) {
|
||||
file, err := os.Open(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
files, err := file.Readdir(-1)
|
||||
func openFile(fs http.FileSystem, name string) (http.File, error) {
|
||||
pathWithSlashes := filepath.ToSlash(name)
|
||||
return fs.Open(pathWithSlashes)
|
||||
}
|
||||
|
||||
func serveFile(c echo.Context, file http.File, info os.FileInfo) error {
|
||||
http.ServeContent(c.Response(), c.Request(), info.Name(), info.ModTime(), file)
|
||||
return nil
|
||||
}
|
||||
|
||||
func listDir(t *template.Template, name string, dir http.File, res *echo.Response) (err error) {
|
||||
files, err := dir.Readdir(-1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
11
vendor/github.com/labstack/echo/v4/middleware/timeout.go
generated
vendored
11
vendor/github.com/labstack/echo/v4/middleware/timeout.go
generated
vendored
@ -1,5 +1,3 @@
|
||||
// +build go1.13
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
@ -94,6 +92,15 @@ func (t echoHandlerFuncWrapper) ServeHTTP(rw http.ResponseWriter, r *http.Reques
|
||||
originalWriter := t.ctx.Response().Writer
|
||||
t.ctx.Response().Writer = rw
|
||||
|
||||
// in case of panic we restore original writer and call panic again
|
||||
// so it could be handled with global middleware Recover()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
t.ctx.Response().Writer = originalWriter
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
err := t.handler(t.ctx)
|
||||
if ctxErr := r.Context().Err(); ctxErr == context.DeadlineExceeded {
|
||||
if err != nil && t.errHandler != nil {
|
||||
|
113
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
113
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
@ -23,6 +23,10 @@ type (
|
||||
methodHandler *methodHandler
|
||||
paramChild *node
|
||||
anyChild *node
|
||||
// isLeaf indicates that node does not have child routes
|
||||
isLeaf bool
|
||||
// isHandler indicates that node has at least one handler registered to it
|
||||
isHandler bool
|
||||
}
|
||||
kind uint8
|
||||
children []*node
|
||||
@ -50,6 +54,20 @@ const (
|
||||
anyLabel = byte('*')
|
||||
)
|
||||
|
||||
func (m *methodHandler) isHandler() bool {
|
||||
return m.connect != nil ||
|
||||
m.delete != nil ||
|
||||
m.get != nil ||
|
||||
m.head != nil ||
|
||||
m.options != nil ||
|
||||
m.patch != nil ||
|
||||
m.post != nil ||
|
||||
m.propfind != nil ||
|
||||
m.put != nil ||
|
||||
m.trace != nil ||
|
||||
m.report != nil
|
||||
}
|
||||
|
||||
// NewRouter returns a new Router instance.
|
||||
func NewRouter(e *Echo) *Router {
|
||||
return &Router{
|
||||
@ -73,6 +91,11 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
|
||||
pnames := []string{} // Param names
|
||||
ppath := path // Pristine path
|
||||
|
||||
if h == nil && r.echo.Logger != nil {
|
||||
// FIXME: in future we should return error
|
||||
r.echo.Logger.Errorf("Adding route without handler function: %v:%v", method, path)
|
||||
}
|
||||
|
||||
for i, lcpIndex := 0, len(path); i < lcpIndex; i++ {
|
||||
if path[i] == ':' {
|
||||
j := i + 1
|
||||
@ -86,6 +109,7 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
|
||||
i, lcpIndex = j, len(path)
|
||||
|
||||
if i == lcpIndex {
|
||||
// path node is last fragment of route path. ie. `/users/:id`
|
||||
r.insert(method, path[:i], h, paramKind, ppath, pnames)
|
||||
} else {
|
||||
r.insert(method, path[:i], nil, paramKind, "", nil)
|
||||
@ -136,6 +160,7 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
||||
currentNode.ppath = ppath
|
||||
currentNode.pnames = pnames
|
||||
}
|
||||
currentNode.isLeaf = currentNode.staticChildren == nil && currentNode.paramChild == nil && currentNode.anyChild == nil
|
||||
} else if lcpLen < prefixLen {
|
||||
// Split node
|
||||
n := newNode(
|
||||
@ -149,7 +174,6 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
||||
currentNode.paramChild,
|
||||
currentNode.anyChild,
|
||||
)
|
||||
|
||||
// Update parent path for all children to new node
|
||||
for _, child := range currentNode.staticChildren {
|
||||
child.parent = n
|
||||
@ -171,6 +195,8 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
||||
currentNode.pnames = nil
|
||||
currentNode.paramChild = nil
|
||||
currentNode.anyChild = nil
|
||||
currentNode.isLeaf = false
|
||||
currentNode.isHandler = false
|
||||
|
||||
// Only Static children could reach here
|
||||
currentNode.addStaticChild(n)
|
||||
@ -188,6 +214,7 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
||||
// Only Static children could reach here
|
||||
currentNode.addStaticChild(n)
|
||||
}
|
||||
currentNode.isLeaf = currentNode.staticChildren == nil && currentNode.paramChild == nil && currentNode.anyChild == nil
|
||||
} else if lcpLen < searchLen {
|
||||
search = search[lcpLen:]
|
||||
c := currentNode.findChildWithLabel(search[0])
|
||||
@ -207,6 +234,7 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
||||
case anyKind:
|
||||
currentNode.anyChild = n
|
||||
}
|
||||
currentNode.isLeaf = currentNode.staticChildren == nil && currentNode.paramChild == nil && currentNode.anyChild == nil
|
||||
} else {
|
||||
// Node already exists
|
||||
if h != nil {
|
||||
@ -233,6 +261,8 @@ func newNode(t kind, pre string, p *node, sc children, mh *methodHandler, ppath
|
||||
methodHandler: mh,
|
||||
paramChild: paramChildren,
|
||||
anyChild: anyChildren,
|
||||
isLeaf: sc == nil && paramChildren == nil && anyChildren == nil,
|
||||
isHandler: mh.isHandler(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,6 +319,12 @@ func (n *node) addHandler(method string, h HandlerFunc) {
|
||||
case REPORT:
|
||||
n.methodHandler.report = h
|
||||
}
|
||||
|
||||
if h != nil {
|
||||
n.isHandler = true
|
||||
} else {
|
||||
n.isHandler = n.methodHandler.isHandler()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *node) findHandler(method string) HandlerFunc {
|
||||
@ -343,6 +379,8 @@ func (r *Router) Find(method, path string, c Context) {
|
||||
currentNode := r.tree // Current node as root
|
||||
|
||||
var (
|
||||
previousBestMatchNode *node
|
||||
matchedHandler HandlerFunc
|
||||
// search stores the remaining path to check for match. By each iteration we move from start of path to end of the path
|
||||
// and search value gets shorter and shorter.
|
||||
search = path
|
||||
@ -362,10 +400,11 @@ func (r *Router) Find(method, path string, c Context) {
|
||||
valid = currentNode != nil
|
||||
|
||||
// Next node type by priority
|
||||
// NOTE: With the current implementation we never backtrack from an `any` route, so `previous.kind` is
|
||||
// always `static` or `any`
|
||||
// If this is changed then for any route next kind would be `static` and this statement should be changed
|
||||
nextNodeKind = previous.kind + 1
|
||||
if previous.kind == anyKind {
|
||||
nextNodeKind = staticKind
|
||||
} else {
|
||||
nextNodeKind = previous.kind + 1
|
||||
}
|
||||
|
||||
if fromKind == staticKind {
|
||||
// when backtracking is done from static kind block we did not change search so nothing to restore
|
||||
@ -380,6 +419,7 @@ func (r *Router) Find(method, path string, c Context) {
|
||||
// for param/any node.prefix value is always `:` so we can not deduce searchIndex from that and must use pValue
|
||||
// for that index as it would also contain part of path we cut off before moving into node we are backtracking from
|
||||
searchIndex -= len(paramValues[paramIndex])
|
||||
paramValues[paramIndex] = ""
|
||||
}
|
||||
search = path[searchIndex:]
|
||||
return
|
||||
@ -421,7 +461,7 @@ func (r *Router) Find(method, path string, c Context) {
|
||||
// goto Any
|
||||
} else {
|
||||
// Not found (this should never be possible for static node we are looking currently)
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,9 +469,17 @@ func (r *Router) Find(method, path string, c Context) {
|
||||
search = search[lcpLen:]
|
||||
searchIndex = searchIndex + lcpLen
|
||||
|
||||
// Finish routing if no remaining search and we are on an leaf node
|
||||
if search == "" && currentNode.ppath != "" {
|
||||
break
|
||||
// Finish routing if no remaining search and we are on a node with handler and matching method type
|
||||
if search == "" && currentNode.isHandler {
|
||||
// check if current node has handler registered for http method we are looking for. we store currentNode as
|
||||
// best matching in case we do no find no more routes matching this path+method
|
||||
if previousBestMatchNode == nil {
|
||||
previousBestMatchNode = currentNode
|
||||
}
|
||||
if h := currentNode.findHandler(method); h != nil {
|
||||
matchedHandler = h
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Static node
|
||||
@ -446,10 +494,16 @@ func (r *Router) Find(method, path string, c Context) {
|
||||
// Param node
|
||||
if child := currentNode.paramChild; search != "" && child != nil {
|
||||
currentNode = child
|
||||
// FIXME: when param node does not have any children then param node should act similarly to any node - consider all remaining search as match
|
||||
i, l := 0, len(search)
|
||||
for ; i < l && search[i] != '/'; i++ {
|
||||
i := 0
|
||||
l := len(search)
|
||||
if currentNode.isLeaf {
|
||||
// when param node does not have any children then param node should act similarly to any node - consider all remaining search as match
|
||||
i = l
|
||||
} else {
|
||||
for ; i < l && search[i] != '/'; i++ {
|
||||
}
|
||||
}
|
||||
|
||||
paramValues[paramIndex] = search[:i]
|
||||
paramIndex++
|
||||
search = search[i:]
|
||||
@ -463,29 +517,50 @@ func (r *Router) Find(method, path string, c Context) {
|
||||
// If any node is found, use remaining path for paramValues
|
||||
currentNode = child
|
||||
paramValues[len(currentNode.pnames)-1] = search
|
||||
break
|
||||
// update indexes/search in case we need to backtrack when no handler match is found
|
||||
paramIndex++
|
||||
searchIndex += +len(search)
|
||||
search = ""
|
||||
|
||||
// check if current node has handler registered for http method we are looking for. we store currentNode as
|
||||
// best matching in case we do no find no more routes matching this path+method
|
||||
if previousBestMatchNode == nil {
|
||||
previousBestMatchNode = currentNode
|
||||
}
|
||||
if h := currentNode.findHandler(method); h != nil {
|
||||
matchedHandler = h
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Let's backtrack to the first possible alternative node of the decision path
|
||||
nk, ok := backtrackToNextNodeKind(anyKind)
|
||||
if !ok {
|
||||
return // No other possibilities on the decision path
|
||||
break // No other possibilities on the decision path
|
||||
} else if nk == paramKind {
|
||||
goto Param
|
||||
} else if nk == anyKind {
|
||||
goto Any
|
||||
} else {
|
||||
// Not found
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ctx.handler = currentNode.findHandler(method)
|
||||
if currentNode == nil && previousBestMatchNode == nil {
|
||||
return // nothing matched at all
|
||||
}
|
||||
|
||||
if matchedHandler != nil {
|
||||
ctx.handler = matchedHandler
|
||||
} else {
|
||||
// use previous match as basis. although we have no matching handler we have path match.
|
||||
// so we can send http.StatusMethodNotAllowed (405) instead of http.StatusNotFound (404)
|
||||
currentNode = previousBestMatchNode
|
||||
ctx.handler = currentNode.checkMethodNotAllowed()
|
||||
}
|
||||
ctx.path = currentNode.ppath
|
||||
ctx.pnames = currentNode.pnames
|
||||
|
||||
if ctx.handler == nil {
|
||||
ctx.handler = currentNode.checkMethodNotAllowed()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user