Files
opencloud/services/proxy/pkg/router/router_test.go
Ralf Haferkamp 07a718dc8e proxy: User ReverseProxy.Rewrite instead of Director
With Go 1.20 the "Rewrite" hook for ReverseProxy was introduced to
supersede of the "Director" hook (see:
a55793835f)

The Rewrite hooks allows for better separation between the incoming and
outgoing request. In particular it makes it pretty easy to set the
correct X-Forwarded-* Headers on the outgoing request.
The need for using "Rewrite" came up when trying to embed
authelia. It uses the X-Forwarded-Host and X-Forwared-Proto headers to
e.g. compute the correct return values for the various endpoints in
.well-known/openid-configuration.
2023-10-16 10:31:39 +02:00

162 lines
4.7 KiB
Go

package router
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/http/httputil"
"net/url"
"testing"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/proxy/pkg/config"
"github.com/owncloud/ocis/v2/services/proxy/pkg/config/defaults"
)
type matchertest struct {
method, endpoint, target string
unprotected bool
matches bool
}
func TestPrefixRouteMatcher(t *testing.T) {
cfg := defaults.DefaultConfig()
cfg.Policies = defaults.DefaultPolicies()
table := []matchertest{
{endpoint: "/foobar", target: "/foobar/baz/some/url", matches: true},
{endpoint: "/fobar", target: "/foobar/baz/some/url", matches: false},
}
for _, test := range table {
u, _ := url.Parse(test.target)
matched := prefixRouteMatcher(test.endpoint, *u)
if matched != test.matches {
t.Errorf("PrefixRouteMatcher returned %t expected %t for endpoint: %s and target %s",
matched, test.matches, test.endpoint, u.String())
}
}
}
func TestQueryRouteMatcher(t *testing.T) {
cfg := defaults.DefaultConfig()
cfg.Policies = defaults.DefaultPolicies()
table := []matchertest{
{endpoint: "/foobar?parameter=true", target: "/foobar/baz/some/url?parameter=true", matches: true},
{endpoint: "/foobar", target: "/foobar/baz/some/url?parameter=true", matches: false},
{endpoint: "/foobar?parameter=false", target: "/foobar/baz/some/url?parameter=true", matches: false},
{endpoint: "/foobar?parameter=false&other=true", target: "/foobar/baz/some/url?parameter=true", matches: false},
{
endpoint: "/foobar?parameter=false&other=true",
target: "/foobar/baz/some/url?parameter=false&other=true",
matches: true,
},
{endpoint: "/fobar", target: "/foobar", matches: false},
}
for _, test := range table {
u, _ := url.Parse(test.target)
matched := queryRouteMatcher(test.endpoint, *u)
if matched != test.matches {
t.Errorf("QueryRouteMatcher returned %t expected %t for endpoint: %s and target %s",
matched, test.matches, test.endpoint, u.String())
}
}
}
func TestRegexRouteMatcher(t *testing.T) {
cfg := defaults.DefaultConfig()
cfg.Policies = defaults.DefaultPolicies()
rt := New(cfg.PolicySelector, cfg.Policies, log.NewLogger())
table := []matchertest{
{endpoint: ".*some\\/url.*parameter=true", target: "/foobar/baz/some/url?parameter=true", matches: true},
{endpoint: "([\\])\\w+", target: "/foobar/baz/some/url?parameter=true", matches: false},
}
for _, test := range table {
u, _ := url.Parse(test.target)
matched := rt.regexRouteMatcher(test.endpoint, *u)
if matched != test.matches {
t.Errorf("RegexRouteMatcher returned %t expected %t for endpoint: %s and target %s",
matched, test.matches, test.endpoint, u.String())
}
}
}
func TestSingleJoiningSlash(t *testing.T) {
type test struct {
a, b, result string
}
table := []test{
{a: "a", b: "b", result: "a/b"},
{a: "a/", b: "b", result: "a/b"},
{a: "a", b: "/b", result: "a/b"},
{a: "a/", b: "/b", result: "a/b"},
}
for _, test := range table {
p := singleJoiningSlash(test.a, test.b)
if p != test.result {
t.Errorf("SingleJoiningSlash got %s expected %s", p, test.result)
}
}
}
func TestRouter(t *testing.T) {
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "ok")
}))
defer svr.Close()
selector := &config.PolicySelector{
Static: &config.StaticSelectorConf{
Policy: "default",
},
}
policies := []config.Policy{
{
Name: "default",
Routes: []config.Route{
{Type: config.PrefixRoute, Endpoint: "/web/unprotected/demo/", Backend: "http://web", Unprotected: true},
{Type: config.PrefixRoute, Endpoint: "/dav", Backend: "http://ocdav"},
{Type: config.PrefixRoute, Method: "REPORT", Endpoint: "/dav", Backend: "http://ocis-webdav"},
},
},
}
router := New(selector, policies, log.NewLogger())
table := []matchertest{
{method: "PROPFIND", endpoint: "/dav/files/demo/", target: "ocdav"},
{method: "REPORT", endpoint: "/dav/files/demo/", target: "ocis-webdav"},
{method: "GET", endpoint: "/web/unprotected/demo/", target: "web", unprotected: true},
}
for _, test := range table {
r := httptest.NewRequest(test.method, test.endpoint, nil)
routingInfo, ok := router.Route(r)
if !ok {
t.Errorf("TestRouter router.Route failed to route the request.")
}
if routingInfo.IsRouteUnprotected() != test.unprotected {
t.Errorf("TestRouter route flag unprotected expected to be %t got %t", test.unprotected, routingInfo.IsRouteUnprotected())
}
pr := &httputil.ProxyRequest{
In: r,
Out: r.Clone(context.Background()),
}
routingInfo.Rewrite()(pr)
if pr.Out.URL.Host != test.target {
t.Errorf("TestRouter got host %s expected %s", pr.Out.URL.Host, test.target)
}
}
}