Added router priority to webui's list and detail page
This commit is contained in:
parent
cd90b9761a
commit
8cd4923e72
43 changed files with 2913 additions and 131 deletions
|
@ -22,8 +22,10 @@ type pageInfo struct {
|
|||
}
|
||||
|
||||
type searchCriterion struct {
|
||||
Search string `url:"search"`
|
||||
Status string `url:"status"`
|
||||
Search string `url:"search"`
|
||||
Status string `url:"status"`
|
||||
ServiceName string `url:"serviceName"`
|
||||
MiddlewareName string `url:"middlewareName"`
|
||||
}
|
||||
|
||||
func newSearchCriterion(query url.Values) *searchCriterion {
|
||||
|
@ -33,12 +35,19 @@ func newSearchCriterion(query url.Values) *searchCriterion {
|
|||
|
||||
search := query.Get("search")
|
||||
status := query.Get("status")
|
||||
serviceName := query.Get("serviceName")
|
||||
middlewareName := query.Get("middlewareName")
|
||||
|
||||
if status == "" && search == "" {
|
||||
if status == "" && search == "" && serviceName == "" && middlewareName == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &searchCriterion{Search: search, Status: status}
|
||||
return &searchCriterion{
|
||||
Search: search,
|
||||
Status: status,
|
||||
ServiceName: serviceName,
|
||||
MiddlewareName: middlewareName,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *searchCriterion) withStatus(name string) bool {
|
||||
|
@ -59,6 +68,34 @@ func (c *searchCriterion) searchIn(values ...string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (c *searchCriterion) filterService(name string) bool {
|
||||
if c.ServiceName == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.Contains(name, "@") {
|
||||
return c.ServiceName == name
|
||||
}
|
||||
|
||||
before, _, _ := strings.Cut(c.ServiceName, "@")
|
||||
|
||||
return before == name
|
||||
}
|
||||
|
||||
func (c *searchCriterion) filterMiddleware(mns []string) bool {
|
||||
if c.MiddlewareName == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, mn := range mns {
|
||||
if c.MiddlewareName == mn {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func pagination(request *http.Request, max int) (pageInfo, error) {
|
||||
perPage, err := getIntParam(request, "per_page", defaultPerPage)
|
||||
if err != nil {
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -69,7 +68,8 @@ func newMiddlewareRepresentation(name string, mi *runtime.MiddlewareInfo) middle
|
|||
func (h Handler) getRouters(rw http.ResponseWriter, request *http.Request) {
|
||||
results := make([]routerRepresentation, 0, len(h.runtimeConfiguration.Routers))
|
||||
|
||||
criterion := newSearchCriterion(request.URL.Query())
|
||||
query := request.URL.Query()
|
||||
criterion := newSearchCriterion(query)
|
||||
|
||||
for name, rt := range h.runtimeConfiguration.Routers {
|
||||
if keepRouter(name, rt, criterion) {
|
||||
|
@ -77,9 +77,7 @@ func (h Handler) getRouters(rw http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
sortRouters(query, results)
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -121,7 +119,8 @@ func (h Handler) getRouter(rw http.ResponseWriter, request *http.Request) {
|
|||
func (h Handler) getServices(rw http.ResponseWriter, request *http.Request) {
|
||||
results := make([]serviceRepresentation, 0, len(h.runtimeConfiguration.Services))
|
||||
|
||||
criterion := newSearchCriterion(request.URL.Query())
|
||||
query := request.URL.Query()
|
||||
criterion := newSearchCriterion(query)
|
||||
|
||||
for name, si := range h.runtimeConfiguration.Services {
|
||||
if keepService(name, si, criterion) {
|
||||
|
@ -129,9 +128,7 @@ func (h Handler) getServices(rw http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
sortServices(query, results)
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -173,7 +170,8 @@ func (h Handler) getService(rw http.ResponseWriter, request *http.Request) {
|
|||
func (h Handler) getMiddlewares(rw http.ResponseWriter, request *http.Request) {
|
||||
results := make([]middlewareRepresentation, 0, len(h.runtimeConfiguration.Middlewares))
|
||||
|
||||
criterion := newSearchCriterion(request.URL.Query())
|
||||
query := request.URL.Query()
|
||||
criterion := newSearchCriterion(query)
|
||||
|
||||
for name, mi := range h.runtimeConfiguration.Middlewares {
|
||||
if keepMiddleware(name, mi, criterion) {
|
||||
|
@ -181,9 +179,7 @@ func (h Handler) getMiddlewares(rw http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
sortMiddlewares(query, results)
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -227,7 +223,10 @@ func keepRouter(name string, item *runtime.RouterInfo, criterion *searchCriterio
|
|||
return true
|
||||
}
|
||||
|
||||
return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name)
|
||||
return criterion.withStatus(item.Status) &&
|
||||
criterion.searchIn(item.Rule, name) &&
|
||||
criterion.filterService(item.Service) &&
|
||||
criterion.filterMiddleware(item.Middlewares)
|
||||
}
|
||||
|
||||
func keepService(name string, item *runtime.ServiceInfo, criterion *searchCriterion) bool {
|
||||
|
|
|
@ -202,6 +202,84 @@ func TestHandler_HTTP(t *testing.T) {
|
|||
jsonFile: "testdata/routers-filtered-search.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "routers filtered by service",
|
||||
path: "/api/http/routers?serviceName=fii-service@myprovider",
|
||||
conf: runtime.Configuration{
|
||||
Routers: map[string]*runtime.RouterInfo{
|
||||
"test@myprovider": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "fii-service@myprovider",
|
||||
Rule: "Host(`fii.bar.other`)",
|
||||
Middlewares: []string{"addPrefixTest", "auth"},
|
||||
},
|
||||
Status: runtime.StatusEnabled,
|
||||
},
|
||||
"foo@otherprovider": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "fii-service",
|
||||
Rule: "Host(`fii.foo.other`)",
|
||||
},
|
||||
Status: runtime.StatusEnabled,
|
||||
},
|
||||
"bar@myprovider": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service@myprovider",
|
||||
Rule: "Host(`foo.bar`)",
|
||||
Middlewares: []string{"auth", "addPrefixTest@anotherprovider"},
|
||||
},
|
||||
Status: runtime.StatusDisabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: expected{
|
||||
statusCode: http.StatusOK,
|
||||
nextPage: "1",
|
||||
jsonFile: "testdata/routers-filtered-serviceName.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "routers filtered by middleware",
|
||||
path: "/api/http/routers?middlewareName=auth",
|
||||
conf: runtime.Configuration{
|
||||
Routers: map[string]*runtime.RouterInfo{
|
||||
"test@myprovider": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "fii-service@myprovider",
|
||||
Rule: "Host(`fii.bar.other`)",
|
||||
Middlewares: []string{"addPrefixTest", "auth"},
|
||||
},
|
||||
Status: runtime.StatusEnabled,
|
||||
},
|
||||
"foo@otherprovider": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "fii-service",
|
||||
Rule: "Host(`fii.foo.other`)",
|
||||
},
|
||||
Status: runtime.StatusEnabled,
|
||||
},
|
||||
"bar@myprovider": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service@myprovider",
|
||||
Rule: "Host(`foo.bar`)",
|
||||
Middlewares: []string{"auth", "addPrefixTest@anotherprovider"},
|
||||
},
|
||||
Status: runtime.StatusDisabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: expected{
|
||||
statusCode: http.StatusOK,
|
||||
nextPage: "1",
|
||||
jsonFile: "testdata/routers-filtered-middlewareName.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "one router by id",
|
||||
path: "/api/http/routers/bar@myprovider",
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -62,7 +61,8 @@ func newTCPMiddlewareRepresentation(name string, mi *runtime.TCPMiddlewareInfo)
|
|||
func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) {
|
||||
results := make([]tcpRouterRepresentation, 0, len(h.runtimeConfiguration.TCPRouters))
|
||||
|
||||
criterion := newSearchCriterion(request.URL.Query())
|
||||
query := request.URL.Query()
|
||||
criterion := newSearchCriterion(query)
|
||||
|
||||
for name, rt := range h.runtimeConfiguration.TCPRouters {
|
||||
if keepTCPRouter(name, rt, criterion) {
|
||||
|
@ -70,9 +70,7 @@ func (h Handler) getTCPRouters(rw http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
sortRouters(query, results)
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -114,7 +112,8 @@ func (h Handler) getTCPRouter(rw http.ResponseWriter, request *http.Request) {
|
|||
func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) {
|
||||
results := make([]tcpServiceRepresentation, 0, len(h.runtimeConfiguration.TCPServices))
|
||||
|
||||
criterion := newSearchCriterion(request.URL.Query())
|
||||
query := request.URL.Query()
|
||||
criterion := newSearchCriterion(query)
|
||||
|
||||
for name, si := range h.runtimeConfiguration.TCPServices {
|
||||
if keepTCPService(name, si, criterion) {
|
||||
|
@ -122,9 +121,7 @@ func (h Handler) getTCPServices(rw http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
sortServices(query, results)
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -166,7 +163,8 @@ func (h Handler) getTCPService(rw http.ResponseWriter, request *http.Request) {
|
|||
func (h Handler) getTCPMiddlewares(rw http.ResponseWriter, request *http.Request) {
|
||||
results := make([]tcpMiddlewareRepresentation, 0, len(h.runtimeConfiguration.Middlewares))
|
||||
|
||||
criterion := newSearchCriterion(request.URL.Query())
|
||||
query := request.URL.Query()
|
||||
criterion := newSearchCriterion(query)
|
||||
|
||||
for name, mi := range h.runtimeConfiguration.TCPMiddlewares {
|
||||
if keepTCPMiddleware(name, mi, criterion) {
|
||||
|
@ -174,9 +172,7 @@ func (h Handler) getTCPMiddlewares(rw http.ResponseWriter, request *http.Request
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
sortMiddlewares(query, results)
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -220,7 +216,10 @@ func keepTCPRouter(name string, item *runtime.TCPRouterInfo, criterion *searchCr
|
|||
return true
|
||||
}
|
||||
|
||||
return criterion.withStatus(item.Status) && criterion.searchIn(item.Rule, name)
|
||||
return criterion.withStatus(item.Status) &&
|
||||
criterion.searchIn(item.Rule, name) &&
|
||||
criterion.filterService(item.Service) &&
|
||||
criterion.filterMiddleware(item.Middlewares)
|
||||
}
|
||||
|
||||
func keepTCPService(name string, item *runtime.TCPServiceInfo, criterion *searchCriterion) bool {
|
||||
|
|
|
@ -193,6 +193,89 @@ func TestHandler_TCP(t *testing.T) {
|
|||
jsonFile: "testdata/tcprouters-filtered-search.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "TCP routers filtered by service",
|
||||
path: "/api/tcp/routers?serviceName=foo-service@myprovider",
|
||||
conf: runtime.Configuration{
|
||||
TCPRouters: map[string]*runtime.TCPRouterInfo{
|
||||
"test@myprovider": {
|
||||
TCPRouter: &dynamic.TCPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service@myprovider",
|
||||
Rule: "Host(`foo.bar.other`)",
|
||||
TLS: &dynamic.RouterTCPTLSConfig{
|
||||
Passthrough: false,
|
||||
},
|
||||
},
|
||||
Status: runtime.StatusEnabled,
|
||||
},
|
||||
"bar@myprovider": {
|
||||
TCPRouter: &dynamic.TCPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service",
|
||||
Rule: "Host(`foo.bar`)",
|
||||
},
|
||||
Status: runtime.StatusWarning,
|
||||
},
|
||||
"foo@myprovider": {
|
||||
TCPRouter: &dynamic.TCPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "bar-service@myprovider",
|
||||
Rule: "Host(`foo.bar`)",
|
||||
},
|
||||
Status: runtime.StatusDisabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: expected{
|
||||
statusCode: http.StatusOK,
|
||||
nextPage: "1",
|
||||
jsonFile: "testdata/tcprouters-filtered-serviceName.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "TCP routers filtered by middleware",
|
||||
path: "/api/tcp/routers?middlewareName=auth",
|
||||
conf: runtime.Configuration{
|
||||
TCPRouters: map[string]*runtime.TCPRouterInfo{
|
||||
"test@myprovider": {
|
||||
TCPRouter: &dynamic.TCPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service@myprovider",
|
||||
Rule: "Host(`foo.bar.other`)",
|
||||
Middlewares: []string{"inflightconn@myprovider"},
|
||||
TLS: &dynamic.RouterTCPTLSConfig{
|
||||
Passthrough: false,
|
||||
},
|
||||
},
|
||||
Status: runtime.StatusEnabled,
|
||||
},
|
||||
"bar@myprovider": {
|
||||
TCPRouter: &dynamic.TCPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service",
|
||||
Rule: "Host(`foo.bar`)",
|
||||
Middlewares: []string{"auth", "inflightconn@myprovider"},
|
||||
},
|
||||
Status: runtime.StatusWarning,
|
||||
},
|
||||
"foo@myprovider": {
|
||||
TCPRouter: &dynamic.TCPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "bar-service@myprovider",
|
||||
Rule: "Host(`foo.bar`)",
|
||||
Middlewares: []string{"inflightconn@myprovider", "auth"},
|
||||
},
|
||||
Status: runtime.StatusDisabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: expected{
|
||||
statusCode: http.StatusOK,
|
||||
nextPage: "1",
|
||||
jsonFile: "testdata/tcprouters-filtered-middlewareName.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "one TCP router by id",
|
||||
path: "/api/tcp/routers/bar@myprovider",
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -46,7 +45,8 @@ func newUDPServiceRepresentation(name string, si *runtime.UDPServiceInfo) udpSer
|
|||
func (h Handler) getUDPRouters(rw http.ResponseWriter, request *http.Request) {
|
||||
results := make([]udpRouterRepresentation, 0, len(h.runtimeConfiguration.UDPRouters))
|
||||
|
||||
criterion := newSearchCriterion(request.URL.Query())
|
||||
query := request.URL.Query()
|
||||
criterion := newSearchCriterion(query)
|
||||
|
||||
for name, rt := range h.runtimeConfiguration.UDPRouters {
|
||||
if keepUDPRouter(name, rt, criterion) {
|
||||
|
@ -54,9 +54,7 @@ func (h Handler) getUDPRouters(rw http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
sortRouters(query, results)
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -98,7 +96,8 @@ func (h Handler) getUDPRouter(rw http.ResponseWriter, request *http.Request) {
|
|||
func (h Handler) getUDPServices(rw http.ResponseWriter, request *http.Request) {
|
||||
results := make([]udpServiceRepresentation, 0, len(h.runtimeConfiguration.UDPServices))
|
||||
|
||||
criterion := newSearchCriterion(request.URL.Query())
|
||||
query := request.URL.Query()
|
||||
criterion := newSearchCriterion(query)
|
||||
|
||||
for name, si := range h.runtimeConfiguration.UDPServices {
|
||||
if keepUDPService(name, si, criterion) {
|
||||
|
@ -106,9 +105,7 @@ func (h Handler) getUDPServices(rw http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].Name < results[j].Name
|
||||
})
|
||||
sortServices(query, results)
|
||||
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -152,7 +149,9 @@ func keepUDPRouter(name string, item *runtime.UDPRouterInfo, criterion *searchCr
|
|||
return true
|
||||
}
|
||||
|
||||
return criterion.withStatus(item.Status) && criterion.searchIn(name)
|
||||
return criterion.withStatus(item.Status) &&
|
||||
criterion.searchIn(name) &&
|
||||
criterion.filterService(item.Service)
|
||||
}
|
||||
|
||||
func keepUDPService(name string, item *runtime.UDPServiceInfo, criterion *searchCriterion) bool {
|
||||
|
|
|
@ -172,6 +172,40 @@ func TestHandler_UDP(t *testing.T) {
|
|||
jsonFile: "testdata/udprouters-filtered-search.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "UDP routers filtered by service",
|
||||
path: "/api/udp/routers?serviceName=foo-service@myprovider",
|
||||
conf: runtime.Configuration{
|
||||
UDPRouters: map[string]*runtime.UDPRouterInfo{
|
||||
"test@myprovider": {
|
||||
UDPRouter: &dynamic.UDPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service@myprovider",
|
||||
},
|
||||
Status: runtime.StatusEnabled,
|
||||
},
|
||||
"bar@myprovider": {
|
||||
UDPRouter: &dynamic.UDPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service",
|
||||
},
|
||||
Status: runtime.StatusWarning,
|
||||
},
|
||||
"foo@myprovider": {
|
||||
UDPRouter: &dynamic.UDPRouter{
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "bar-service@myprovider",
|
||||
},
|
||||
Status: runtime.StatusDisabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: expected{
|
||||
statusCode: http.StatusOK,
|
||||
nextPage: "1",
|
||||
jsonFile: "testdata/udprouters-filtered-serviceName.json",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "one UDP router by id",
|
||||
path: "/api/udp/routers/bar@myprovider",
|
||||
|
|
386
pkg/api/sort.go
Normal file
386
pkg/api/sort.go
Normal file
|
@ -0,0 +1,386 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
const (
|
||||
sortByParam = "sortBy"
|
||||
directionParam = "direction"
|
||||
)
|
||||
|
||||
const (
|
||||
ascendantSorting = "asc"
|
||||
descendantSorting = "desc"
|
||||
)
|
||||
|
||||
type orderedWithName interface {
|
||||
name() string
|
||||
}
|
||||
|
||||
type orderedRouter interface {
|
||||
orderedWithName
|
||||
|
||||
provider() string
|
||||
priority() int
|
||||
status() string
|
||||
rule() string
|
||||
service() string
|
||||
entryPointsCount() int
|
||||
}
|
||||
|
||||
func sortRouters[T orderedRouter](values url.Values, routers []T) {
|
||||
sortBy := values.Get(sortByParam)
|
||||
|
||||
direction := values.Get(directionParam)
|
||||
if direction == "" {
|
||||
direction = ascendantSorting
|
||||
}
|
||||
|
||||
switch sortBy {
|
||||
case "name":
|
||||
sortByName(direction, routers)
|
||||
|
||||
case "provider":
|
||||
sortByFunc(direction, routers, func(i int) string { return routers[i].provider() })
|
||||
|
||||
case "priority":
|
||||
sortByFunc(direction, routers, func(i int) int { return routers[i].priority() })
|
||||
|
||||
case "status":
|
||||
sortByFunc(direction, routers, func(i int) string { return routers[i].status() })
|
||||
|
||||
case "rule":
|
||||
sortByFunc(direction, routers, func(i int) string { return routers[i].rule() })
|
||||
|
||||
case "service":
|
||||
sortByFunc(direction, routers, func(i int) string { return routers[i].service() })
|
||||
|
||||
case "entryPoints":
|
||||
sortByFunc(direction, routers, func(i int) int { return routers[i].entryPointsCount() })
|
||||
|
||||
default:
|
||||
sortByName(direction, routers)
|
||||
}
|
||||
}
|
||||
|
||||
func (r routerRepresentation) name() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
func (r routerRepresentation) provider() string {
|
||||
return r.Provider
|
||||
}
|
||||
|
||||
func (r routerRepresentation) priority() int {
|
||||
return r.Priority
|
||||
}
|
||||
|
||||
func (r routerRepresentation) status() string {
|
||||
return r.Status
|
||||
}
|
||||
|
||||
func (r routerRepresentation) rule() string {
|
||||
return r.Rule
|
||||
}
|
||||
|
||||
func (r routerRepresentation) service() string {
|
||||
return r.Service
|
||||
}
|
||||
|
||||
func (r routerRepresentation) entryPointsCount() int {
|
||||
return len(r.EntryPoints)
|
||||
}
|
||||
|
||||
func (r tcpRouterRepresentation) name() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
func (r tcpRouterRepresentation) provider() string {
|
||||
return r.Provider
|
||||
}
|
||||
|
||||
func (r tcpRouterRepresentation) priority() int {
|
||||
return r.Priority
|
||||
}
|
||||
|
||||
func (r tcpRouterRepresentation) status() string {
|
||||
return r.Status
|
||||
}
|
||||
|
||||
func (r tcpRouterRepresentation) rule() string {
|
||||
return r.Rule
|
||||
}
|
||||
|
||||
func (r tcpRouterRepresentation) service() string {
|
||||
return r.Service
|
||||
}
|
||||
|
||||
func (r tcpRouterRepresentation) entryPointsCount() int {
|
||||
return len(r.EntryPoints)
|
||||
}
|
||||
|
||||
func (r udpRouterRepresentation) name() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
func (r udpRouterRepresentation) provider() string {
|
||||
return r.Provider
|
||||
}
|
||||
|
||||
func (r udpRouterRepresentation) priority() int {
|
||||
// noop
|
||||
return 0
|
||||
}
|
||||
|
||||
func (r udpRouterRepresentation) status() string {
|
||||
return r.Status
|
||||
}
|
||||
|
||||
func (r udpRouterRepresentation) rule() string {
|
||||
// noop
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r udpRouterRepresentation) service() string {
|
||||
return r.Service
|
||||
}
|
||||
|
||||
func (r udpRouterRepresentation) entryPointsCount() int {
|
||||
return len(r.EntryPoints)
|
||||
}
|
||||
|
||||
type orderedService interface {
|
||||
orderedWithName
|
||||
|
||||
resourceType() string
|
||||
serversCount() int
|
||||
provider() string
|
||||
status() string
|
||||
}
|
||||
|
||||
func sortServices[T orderedService](values url.Values, services []T) {
|
||||
sortBy := values.Get(sortByParam)
|
||||
|
||||
direction := values.Get(directionParam)
|
||||
if direction == "" {
|
||||
direction = ascendantSorting
|
||||
}
|
||||
|
||||
switch sortBy {
|
||||
case "name":
|
||||
sortByName(direction, services)
|
||||
|
||||
case "type":
|
||||
sortByFunc(direction, services, func(i int) string { return services[i].resourceType() })
|
||||
|
||||
case "servers":
|
||||
sortByFunc(direction, services, func(i int) int { return services[i].serversCount() })
|
||||
|
||||
case "provider":
|
||||
sortByFunc(direction, services, func(i int) string { return services[i].provider() })
|
||||
|
||||
case "status":
|
||||
sortByFunc(direction, services, func(i int) string { return services[i].status() })
|
||||
|
||||
default:
|
||||
sortByName(direction, services)
|
||||
}
|
||||
}
|
||||
|
||||
func (s serviceRepresentation) name() string {
|
||||
return s.Name
|
||||
}
|
||||
|
||||
func (s serviceRepresentation) resourceType() string {
|
||||
return s.Type
|
||||
}
|
||||
|
||||
func (s serviceRepresentation) serversCount() int {
|
||||
// TODO: maybe disable that data point altogether,
|
||||
// if we can't/won't compute a fully correct (recursive) result.
|
||||
// Or "redefine" it as only the top-level count?
|
||||
// Note: The current algo is equivalent to the webui one.
|
||||
if s.LoadBalancer == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(s.LoadBalancer.Servers)
|
||||
}
|
||||
|
||||
func (s serviceRepresentation) provider() string {
|
||||
return s.Provider
|
||||
}
|
||||
|
||||
func (s serviceRepresentation) status() string {
|
||||
return s.Status
|
||||
}
|
||||
|
||||
func (s tcpServiceRepresentation) name() string {
|
||||
return s.Name
|
||||
}
|
||||
|
||||
func (s tcpServiceRepresentation) resourceType() string {
|
||||
return s.Type
|
||||
}
|
||||
|
||||
func (s tcpServiceRepresentation) serversCount() int {
|
||||
// TODO: maybe disable that data point altogether,
|
||||
// if we can't/won't compute a fully correct (recursive) result.
|
||||
// Or "redefine" it as only the top-level count?
|
||||
// Note: The current algo is equivalent to the webui one.
|
||||
if s.LoadBalancer == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(s.LoadBalancer.Servers)
|
||||
}
|
||||
|
||||
func (s tcpServiceRepresentation) provider() string {
|
||||
return s.Provider
|
||||
}
|
||||
|
||||
func (s tcpServiceRepresentation) status() string {
|
||||
return s.Status
|
||||
}
|
||||
|
||||
func (s udpServiceRepresentation) name() string {
|
||||
return s.Name
|
||||
}
|
||||
|
||||
func (s udpServiceRepresentation) resourceType() string {
|
||||
return s.Type
|
||||
}
|
||||
|
||||
func (s udpServiceRepresentation) serversCount() int {
|
||||
// TODO: maybe disable that data point altogether,
|
||||
// if we can't/won't compute a fully correct (recursive) result.
|
||||
// Or "redefine" it as only the top-level count?
|
||||
// Note: The current algo is equivalent to the webui one.
|
||||
if s.LoadBalancer == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(s.LoadBalancer.Servers)
|
||||
}
|
||||
|
||||
func (s udpServiceRepresentation) provider() string {
|
||||
return s.Provider
|
||||
}
|
||||
|
||||
func (s udpServiceRepresentation) status() string {
|
||||
return s.Status
|
||||
}
|
||||
|
||||
type orderedMiddleware interface {
|
||||
orderedWithName
|
||||
|
||||
resourceType() string
|
||||
provider() string
|
||||
status() string
|
||||
}
|
||||
|
||||
func sortMiddlewares[T orderedMiddleware](values url.Values, middlewares []T) {
|
||||
sortBy := values.Get(sortByParam)
|
||||
|
||||
direction := values.Get(directionParam)
|
||||
if direction == "" {
|
||||
direction = ascendantSorting
|
||||
}
|
||||
|
||||
switch sortBy {
|
||||
case "name":
|
||||
sortByName(direction, middlewares)
|
||||
|
||||
case "type":
|
||||
sortByFunc(direction, middlewares, func(i int) string { return middlewares[i].resourceType() })
|
||||
|
||||
case "provider":
|
||||
sortByFunc(direction, middlewares, func(i int) string { return middlewares[i].provider() })
|
||||
|
||||
case "status":
|
||||
sortByFunc(direction, middlewares, func(i int) string { return middlewares[i].status() })
|
||||
|
||||
default:
|
||||
sortByName(direction, middlewares)
|
||||
}
|
||||
}
|
||||
|
||||
func (m middlewareRepresentation) name() string {
|
||||
return m.Name
|
||||
}
|
||||
|
||||
func (m middlewareRepresentation) resourceType() string {
|
||||
return m.Type
|
||||
}
|
||||
|
||||
func (m middlewareRepresentation) provider() string {
|
||||
return m.Provider
|
||||
}
|
||||
|
||||
func (m middlewareRepresentation) status() string {
|
||||
return m.Status
|
||||
}
|
||||
|
||||
func (m tcpMiddlewareRepresentation) name() string {
|
||||
return m.Name
|
||||
}
|
||||
|
||||
func (m tcpMiddlewareRepresentation) resourceType() string {
|
||||
return m.Type
|
||||
}
|
||||
|
||||
func (m tcpMiddlewareRepresentation) provider() string {
|
||||
return m.Provider
|
||||
}
|
||||
|
||||
func (m tcpMiddlewareRepresentation) status() string {
|
||||
return m.Status
|
||||
}
|
||||
|
||||
type orderedByName interface {
|
||||
orderedWithName
|
||||
}
|
||||
|
||||
func sortByName[T orderedByName](direction string, results []T) {
|
||||
// Ascending
|
||||
if direction == ascendantSorting {
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].name() < results[j].name()
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Descending
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].name() > results[j].name()
|
||||
})
|
||||
}
|
||||
|
||||
func sortByFunc[T orderedWithName, U constraints.Ordered](direction string, results []T, fn func(int) U) {
|
||||
// Ascending
|
||||
if direction == ascendantSorting {
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
if fn(i) == fn(j) {
|
||||
return results[i].name() < results[j].name()
|
||||
}
|
||||
|
||||
return fn(i) < fn(j)
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Descending
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
if fn(i) == fn(j) {
|
||||
return results[i].name() > results[j].name()
|
||||
}
|
||||
|
||||
return fn(i) > fn(j)
|
||||
})
|
||||
}
|
1689
pkg/api/sort_test.go
Normal file
1689
pkg/api/sort_test.go
Normal file
File diff suppressed because it is too large
Load diff
36
pkg/api/testdata/routers-filtered-middlewareName.json
vendored
Normal file
36
pkg/api/testdata/routers-filtered-middlewareName.json
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
[
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"auth",
|
||||
"addPrefixTest@anotherprovider"
|
||||
],
|
||||
"name": "bar@myprovider",
|
||||
"provider": "myprovider",
|
||||
"rule": "Host(`foo.bar`)",
|
||||
"service": "foo-service@myprovider",
|
||||
"status": "disabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"addPrefixTest",
|
||||
"auth"
|
||||
],
|
||||
"name": "test@myprovider",
|
||||
"provider": "myprovider",
|
||||
"rule": "Host(`fii.bar.other`)",
|
||||
"service": "fii-service@myprovider",
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
}
|
||||
]
|
32
pkg/api/testdata/routers-filtered-serviceName.json
vendored
Normal file
32
pkg/api/testdata/routers-filtered-serviceName.json
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
[
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"name": "foo@otherprovider",
|
||||
"provider": "otherprovider",
|
||||
"rule": "Host(`fii.foo.other`)",
|
||||
"service": "fii-service",
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"addPrefixTest",
|
||||
"auth"
|
||||
],
|
||||
"name": "test@myprovider",
|
||||
"provider": "myprovider",
|
||||
"rule": "Host(`fii.bar.other`)",
|
||||
"service": "fii-service@myprovider",
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
}
|
||||
]
|
36
pkg/api/testdata/tcprouters-filtered-middlewareName.json
vendored
Normal file
36
pkg/api/testdata/tcprouters-filtered-middlewareName.json
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
[
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"auth",
|
||||
"inflightconn@myprovider"
|
||||
],
|
||||
"name": "bar@myprovider",
|
||||
"provider": "myprovider",
|
||||
"rule": "Host(`foo.bar`)",
|
||||
"service": "foo-service",
|
||||
"status": "warning",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"middlewares": [
|
||||
"inflightconn@myprovider",
|
||||
"auth"
|
||||
],
|
||||
"name": "foo@myprovider",
|
||||
"provider": "myprovider",
|
||||
"rule": "Host(`foo.bar`)",
|
||||
"service": "bar-service@myprovider",
|
||||
"status": "disabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
}
|
||||
]
|
31
pkg/api/testdata/tcprouters-filtered-serviceName.json
vendored
Normal file
31
pkg/api/testdata/tcprouters-filtered-serviceName.json
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
[
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"name": "bar@myprovider",
|
||||
"provider": "myprovider",
|
||||
"rule": "Host(`foo.bar`)",
|
||||
"service": "foo-service",
|
||||
"status": "warning",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"name": "test@myprovider",
|
||||
"provider": "myprovider",
|
||||
"rule": "Host(`foo.bar.other`)",
|
||||
"service": "foo-service@myprovider",
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
],
|
||||
"tls": {
|
||||
"passthrough": false
|
||||
}
|
||||
}
|
||||
]
|
26
pkg/api/testdata/udprouters-filtered-serviceName.json
vendored
Normal file
26
pkg/api/testdata/udprouters-filtered-serviceName.json
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
[
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"name": "bar@myprovider",
|
||||
"provider": "myprovider",
|
||||
"service": "foo-service",
|
||||
"status": "warning",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
},
|
||||
{
|
||||
"entryPoints": [
|
||||
"web"
|
||||
],
|
||||
"name": "test@myprovider",
|
||||
"provider": "myprovider",
|
||||
"service": "foo-service@myprovider",
|
||||
"status": "enabled",
|
||||
"using": [
|
||||
"web"
|
||||
]
|
||||
}
|
||||
]
|
|
@ -46,6 +46,12 @@ func (m *Muxer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||
http.NotFoundHandler().ServeHTTP(rw, req)
|
||||
}
|
||||
|
||||
// GetRulePriority computes the priority for a given rule.
|
||||
// The priority is calculated using the length of rule.
|
||||
func GetRulePriority(rule string) int {
|
||||
return len(rule)
|
||||
}
|
||||
|
||||
// AddRoute add a new route to the router.
|
||||
func (m *Muxer) AddRoute(rule string, priority int, handler http.Handler) error {
|
||||
parse, err := m.parser.Parse(rule)
|
||||
|
@ -64,10 +70,6 @@ func (m *Muxer) AddRoute(rule string, priority int, handler http.Handler) error
|
|||
return fmt.Errorf("error while adding rule %s: %w", rule, err)
|
||||
}
|
||||
|
||||
if priority == 0 {
|
||||
priority = len(rule)
|
||||
}
|
||||
|
||||
m.routes = append(m.routes, &route{
|
||||
handler: handler,
|
||||
matchers: matchers,
|
||||
|
|
|
@ -376,6 +376,10 @@ func Test_addRoutePriority(t *testing.T) {
|
|||
w.Header().Set("X-From", route.xFrom)
|
||||
})
|
||||
|
||||
if route.priority == 0 {
|
||||
route.priority = GetRulePriority(route.rule)
|
||||
}
|
||||
|
||||
err := muxer.AddRoute(route.rule, route.priority, handler)
|
||||
require.NoError(t, err, route.rule)
|
||||
}
|
||||
|
@ -517,3 +521,26 @@ func TestEmptyHost(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRulePriority(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
rule string
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
desc: "simple rule",
|
||||
rule: "Host(`example.org`)",
|
||||
expected: 19,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert.Equal(t, test.expected, GetRulePriority(test.rule))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,38 @@ func (m Muxer) Match(meta ConnData) (tcp.Handler, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
// GetRulePriority computes the priority for a given rule.
|
||||
// The priority is calculated using the length of rule.
|
||||
// There is a special case where the HostSNI(`*`) has a priority of -1.
|
||||
func GetRulePriority(rule string) int {
|
||||
catchAllParser, err := rules.NewParser([]string{"HostSNI"})
|
||||
if err != nil {
|
||||
return len(rule)
|
||||
}
|
||||
|
||||
parse, err := catchAllParser.Parse(rule)
|
||||
if err != nil {
|
||||
return len(rule)
|
||||
}
|
||||
|
||||
buildTree, ok := parse.(rules.TreeBuilder)
|
||||
if !ok {
|
||||
return len(rule)
|
||||
}
|
||||
|
||||
ruleTree := buildTree()
|
||||
|
||||
// Special case for when the catchAll fallback is present.
|
||||
// When no user-defined priority is found, the lowest computable priority minus one is used,
|
||||
// in order to make the fallback the last to be evaluated.
|
||||
if ruleTree.RuleLeft == nil && ruleTree.RuleRight == nil && len(ruleTree.Value) == 1 &&
|
||||
ruleTree.Value[0] == "*" && strings.EqualFold(ruleTree.Matcher, "HostSNI") {
|
||||
return -1
|
||||
}
|
||||
|
||||
return len(rule)
|
||||
}
|
||||
|
||||
// AddRoute adds a new route, associated to the given handler, at the given
|
||||
// priority, to the muxer.
|
||||
func (m *Muxer) AddRoute(rule string, priority int, handler tcp.Handler) error {
|
||||
|
@ -98,18 +130,6 @@ func (m *Muxer) AddRoute(rule string, priority int, handler tcp.Handler) error {
|
|||
catchAll = ruleTree.Value[0] == "*" && strings.EqualFold(ruleTree.Matcher, "HostSNI")
|
||||
}
|
||||
|
||||
// Special case for when the catchAll fallback is present.
|
||||
// When no user-defined priority is found, the lowest computable priority minus one is used,
|
||||
// in order to make the fallback the last to be evaluated.
|
||||
if priority == 0 && catchAll {
|
||||
priority = -1
|
||||
}
|
||||
|
||||
// Default value, which means the user has not set it, so we'll compute it.
|
||||
if priority == 0 {
|
||||
priority = len(rule)
|
||||
}
|
||||
|
||||
newRoute := &route{
|
||||
handler: handler,
|
||||
matchers: matchers,
|
||||
|
|
|
@ -444,6 +444,39 @@ func Test_Priority(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetRulePriority(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
rule string
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
desc: "simple rule",
|
||||
rule: "HostSNI(`example.org`)",
|
||||
expected: 22,
|
||||
},
|
||||
{
|
||||
desc: "HostSNI(`*`) rule",
|
||||
rule: "HostSNI(`*`)",
|
||||
expected: -1,
|
||||
},
|
||||
{
|
||||
desc: "strange HostSNI(`*`) rule",
|
||||
rule: " HostSNI ( `*` ) ",
|
||||
expected: -1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert.Equal(t, test.expected, GetRulePriority(test.rule))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type fakeConn struct {
|
||||
call map[string]int
|
||||
remoteAddr net.Addr
|
||||
|
|
|
@ -119,6 +119,10 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
logger := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger()
|
||||
ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerName))
|
||||
|
||||
if routerConfig.Priority == 0 {
|
||||
routerConfig.Priority = httpmuxer.GetRulePriority(routerConfig.Rule)
|
||||
}
|
||||
|
||||
handler, err := m.buildRouterHandler(ctxRouter, routerName, routerConfig)
|
||||
if err != nil {
|
||||
routerConfig.AddError(err, true)
|
||||
|
@ -126,8 +130,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
continue
|
||||
}
|
||||
|
||||
err = muxer.AddRoute(routerConfig.Rule, routerConfig.Priority, handler)
|
||||
if err != nil {
|
||||
if err = muxer.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil {
|
||||
routerConfig.AddError(err, true)
|
||||
logger.Error().Err(err).Send()
|
||||
continue
|
||||
|
|
|
@ -264,6 +264,10 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim
|
|||
logger := log.Ctx(ctx).With().Str(logs.RouterName, routerName).Logger()
|
||||
ctxRouter := logger.WithContext(provider.AddInContext(ctx, routerName))
|
||||
|
||||
if routerConfig.Priority == 0 {
|
||||
routerConfig.Priority = tcpmuxer.GetRulePriority(routerConfig.Rule)
|
||||
}
|
||||
|
||||
if routerConfig.Service == "" {
|
||||
err := errors.New("the service is missing on the router")
|
||||
routerConfig.AddError(err, true)
|
||||
|
@ -306,6 +310,7 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim
|
|||
|
||||
if routerConfig.TLS == nil {
|
||||
logger.Debug().Msgf("Adding route for %q", routerConfig.Rule)
|
||||
|
||||
if err := router.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil {
|
||||
routerConfig.AddError(err, true)
|
||||
logger.Error().Err(err).Send()
|
||||
|
@ -315,6 +320,7 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim
|
|||
|
||||
if routerConfig.TLS.Passthrough {
|
||||
logger.Debug().Msgf("Adding Passthrough route for %q", routerConfig.Rule)
|
||||
|
||||
if err := router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil {
|
||||
routerConfig.AddError(err, true)
|
||||
logger.Error().Err(err).Send()
|
||||
|
@ -349,11 +355,11 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim
|
|||
|
||||
logger.Debug().Msgf("Adding special TLS closing route for %q because broken TLS options %s", routerConfig.Rule, tlsOptionsName)
|
||||
|
||||
err = router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, &brokenTLSRouter{})
|
||||
if err != nil {
|
||||
if err := router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, &brokenTLSRouter{}); err != nil {
|
||||
routerConfig.AddError(err, true)
|
||||
logger.Error().Err(err).Send()
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -383,10 +389,10 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim
|
|||
|
||||
logger.Debug().Msgf("Adding TLS route for %q", routerConfig.Rule)
|
||||
|
||||
err = router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, handler)
|
||||
if err != nil {
|
||||
if err := router.muxerTCPTLS.AddRoute(routerConfig.Rule, routerConfig.Priority, handler); err != nil {
|
||||
routerConfig.AddError(err, true)
|
||||
logger.Error().Err(err).Send()
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -268,8 +268,7 @@ func (r *Router) SetHTTPSForwarder(handler tcp.Handler) {
|
|||
|
||||
// muxerHTTPS only contains single HostSNI rules (and no other kind of rules),
|
||||
// so there's no need for specifying a priority for them.
|
||||
err := r.muxerHTTPS.AddRoute("HostSNI(`"+sniHost+"`)", 0, tcpHandler)
|
||||
if err != nil {
|
||||
if err := r.muxerHTTPS.AddRoute("HostSNI(`"+sniHost+"`)", 0, tcpHandler); err != nil {
|
||||
log.Error().Err(err).Msg("Error while adding route for host")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue