Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for header based route #565

Merged
merged 7 commits into from
Jul 2, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pixiu/pkg/common/http/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func TestCreateHttpConnectionManager(t *testing.T) {
RouteTrie: trie.NewTrieWithDefault("POST/api/v1/**", model.RouteAction{
Cluster: "test_dubbo",
ClusterNotFoundResponseCode: 505,
}),
}, nil),
Dynamic: false,
},
HTTPFilters: []*model.HTTPFilter{
Expand Down
52 changes: 49 additions & 3 deletions pixiu/pkg/common/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@
package router

import (
stdHttp "net/http"
"strings"
"sync"
)

import (
"github.com/pkg/errors"
)

import (
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/constant"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/router/trie"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/util/stringutil"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/context/http"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/model"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/server"
)
Expand All @@ -46,6 +52,7 @@ func CreateRouterCoordinator(routeConfig *model.RouteConfiguration) *RouterCoord
server.GetRouterManager().AddRouterListener(rc)
}
rc.initTrie()
rc.initRegex()
return rc
}

Expand All @@ -54,14 +61,38 @@ func (rm *RouterCoordinator) Route(hc *http.HttpContext) (*model.RouteAction, er
rm.rw.RLock()
defer rm.rw.RUnlock()

return rm.activeConfig.Route(hc.Request)
return rm.route(hc.Request)
}

func (rm *RouterCoordinator) RouteByPathAndName(path, method string) (*model.RouteAction, error) {
rm.rw.RLock()
defer rm.rw.RUnlock()

return rm.activeConfig.RouteByPathAndMethod(path, method)
return rm.activeConfig.RouteByPathAndMethod(path, method, nil)
}

func (rm *RouterCoordinator) route(req *stdHttp.Request) (*model.RouteAction, error) {
// match those route that only contains headers first
var matched []*model.Router
for _, route := range rm.activeConfig.Routes {
if len(route.Match.Prefix) > 0 {
continue
}
if route.Match.MatchHeader(req) {
matched = append(matched, route)
}
}

// always return the first match of header if got any
if len(matched) > 0 {
if len(matched[0].Route.Cluster) == 0 {
return nil, errors.New("action is nil. please check your configuration.")
}
return &matched[0].Route, nil
}

// match those route that only contains prefix or both prefix and header
return rm.activeConfig.Route(req)
}

func getTrieKey(method string, path string, isPrefix bool) string {
Expand All @@ -83,6 +114,21 @@ func (rm *RouterCoordinator) initTrie() {
}
}

func (rm *RouterCoordinator) initRegex() {
for _, router := range rm.activeConfig.Routes {
headers := router.Match.Headers
for i := range headers {
if headers[i].Regex && len(headers[i].Values) > 0 {
// regexp always use first value of header
err := headers[i].SetValueRegex(headers[i].Values[0])
if err != nil {
logger.Errorf("invalid regexp in headers[%d]: %v", i, err)
shawnh2 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
}

// OnAddRouter add router
func (rm *RouterCoordinator) OnAddRouter(r *model.Router) {
//TODO: lock move to trie node
Expand All @@ -99,7 +145,7 @@ func (rm *RouterCoordinator) OnAddRouter(r *model.Router) {
} else {
key = getTrieKey(method, r.Match.Path, isPrefix)
}
_, _ = rm.activeConfig.RouteTrie.Put(key, r.Route)
_, _ = rm.activeConfig.RouteTrie.Put(key, r.Route, r.Match.HeaderMap())
}
}

Expand Down
Loading