Skip to content

Commit

Permalink
fix(server): Fix hostrouter to ensure wildcard domains are tested in …
Browse files Browse the repository at this point in the history
…the injection order
  • Loading branch information
oxyno-zeta committed Jul 3, 2021
1 parent 7c07dcb commit 178cb61
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 30 deletions.
19 changes: 12 additions & 7 deletions pkg/s3-proxy/server/hostrouter.go
Expand Up @@ -12,27 +12,32 @@ import (
// Fork dead project https://github.com/go-chi/hostrouter/
// Add wildcard support, not found handler and internal server handler
// Remove not necessary parts
// Update to ensure that all wildcard domains will be tested in the injection order

type HostRouter struct {
domainList []string
routes map[string]chi.Router
notFoundHandler http.HandlerFunc
internalServerHandler func(err error) http.HandlerFunc
}

func NewHostRouter(notFoundHandler http.HandlerFunc, internalServerHandler func(err error) http.HandlerFunc) HostRouter {
return HostRouter{
domainList: []string{},
routes: map[string]chi.Router{},
notFoundHandler: notFoundHandler,
internalServerHandler: internalServerHandler,
}
}

func (hr HostRouter) Get(domain string) chi.Router {
return hr.routes[domain]
func (hr *HostRouter) Get(domain string) chi.Router {
return hr.routes[strings.ToLower(domain)]
}

func (hr HostRouter) Map(host string, h chi.Router) {
hr.routes[strings.ToLower(host)] = h
func (hr *HostRouter) Map(host string, h chi.Router) {
lowercaseHost := strings.ToLower(host)
hr.domainList = append(hr.domainList, lowercaseHost)
hr.routes[lowercaseHost] = h
}

func (hr HostRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -64,16 +69,16 @@ func (hr HostRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
hr.notFoundHandler(w, r)
}

func (hr HostRouter) getRouterWithWildcard(host string) (chi.Router, error) {
for wh, rt := range hr.routes {
func (hr *HostRouter) getRouterWithWildcard(host string) (chi.Router, error) {
for _, wh := range hr.domainList {
g, err := glob.Compile(wh)
// Check if error exists
if err != nil {
return nil, err
}
// Check if wildcard host match current host
if g.Match(host) {
return rt, nil
return hr.routes[wh], nil
}
}

Expand Down
53 changes: 30 additions & 23 deletions pkg/s3-proxy/server/hostrouter_test.go
Expand Up @@ -28,81 +28,88 @@ func TestHostRouter_ServeHTTP(t *testing.T) {
w.Write([]byte("localhost"))
})

type routeInput struct {
domain string
router chi.Router
}
tests := []struct {
name string
inputURL string
routes map[string]chi.Router
routes []*routeInput
expectedStatus int
expectedBody string
}{
{
name: "should match the star glob",
inputURL: "http://fake/",
routes: map[string]chi.Router{
"localhost": localhostRouter,
"*.localhost": starLocalhostRouter,
"*": starRouter,
routes: []*routeInput{
{"localhost", localhostRouter},
{"*.localhost", starLocalhostRouter},
{"*", starRouter},
},
expectedStatus: 200,
expectedBody: "star",
},
{
name: "should match the perfect host",
inputURL: "http://localhost/",
routes: map[string]chi.Router{
"localhost": localhostRouter,
"*.localhost": starLocalhostRouter,
"*": starRouter,
routes: []*routeInput{
{"localhost", localhostRouter},
{"*.localhost", starLocalhostRouter},
{"*", starRouter},
},
expectedStatus: 200,
expectedBody: "localhost",
},
{
name: "should match the glob host",
inputURL: "http://api.localhost/",
routes: map[string]chi.Router{
"localhost": localhostRouter,
"*.localhost": starLocalhostRouter,
"*": starRouter,
routes: []*routeInput{
{"localhost", localhostRouter},
{"*.localhost", starLocalhostRouter},
{"*", starRouter},
},
expectedStatus: 200,
expectedBody: "starLocalhost",
},
{
name: "should match the glob host (2)",
inputURL: "http://ui.localhost/",
routes: map[string]chi.Router{
"localhost": localhostRouter,
"*.localhost": starLocalhostRouter,
"*": starRouter,
routes: []*routeInput{
{"localhost", localhostRouter},
{"*.localhost", starLocalhostRouter},
{"*", starRouter},
},
expectedStatus: 200,
expectedBody: "starLocalhost",
},
{
name: "should return a not found error",
inputURL: "http://ui.localhost/",
routes: map[string]chi.Router{
"localhost": localhostRouter,
routes: []*routeInput{
{"localhost", localhostRouter},
},
expectedStatus: 404,
expectedBody: "hostrouter not found",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hr := HostRouter{
routes: tt.routes,
notFoundHandler: func(w http.ResponseWriter, r *http.Request) {
hr := NewHostRouter(
func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404)
w.Write([]byte("hostrouter not found"))
},
internalServerHandler: func(err error) http.HandlerFunc {
func(err error) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)
w.Write([]byte("hostrouter internal server error"))
}
},
)

for _, it := range tt.routes {
hr.Map(it.domain, it.router)
}

w := httptest.NewRecorder()
Expand Down

0 comments on commit 178cb61

Please sign in to comment.