mirror of
https://github.com/nais/wonderwall.git
synced 2026-02-14 17:49:54 +00:00
518 lines
15 KiB
Go
518 lines
15 KiB
Go
package url_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/nais/wonderwall/pkg/mock"
|
|
"github.com/nais/wonderwall/pkg/url"
|
|
)
|
|
|
|
type expected struct {
|
|
canonical string
|
|
clean string
|
|
}
|
|
|
|
func TestDefault(t *testing.T) {
|
|
cfg := mock.Config()
|
|
cfg.Ingresses = []string{
|
|
"http://wonderwall",
|
|
"http://wonderwall/some-path",
|
|
}
|
|
ingresses := mock.Ingresses(cfg)
|
|
|
|
h := url.NewStandaloneRedirect()
|
|
|
|
for _, tt := range []struct {
|
|
name string
|
|
url string
|
|
expected expected
|
|
}{
|
|
{
|
|
name: "no redirect param",
|
|
url: "/",
|
|
expected: expected{
|
|
canonical: "/",
|
|
clean: "/",
|
|
},
|
|
},
|
|
{
|
|
name: "empty redirect param",
|
|
url: "/?redirect=",
|
|
expected: expected{
|
|
canonical: "/",
|
|
clean: "/?redirect=",
|
|
},
|
|
},
|
|
{
|
|
name: "no redirect param, context path",
|
|
url: "/some-path",
|
|
expected: expected{
|
|
canonical: "/some-path",
|
|
clean: "/some-path",
|
|
},
|
|
},
|
|
{
|
|
name: "empty redirect param, context path",
|
|
url: "/some-path?redirect=",
|
|
expected: expected{
|
|
canonical: "/some-path",
|
|
clean: "/some-path?redirect=",
|
|
},
|
|
},
|
|
{
|
|
name: "with query parameters",
|
|
url: "/?redirect=%2Fpath%3Fgnu%3Dnotunix",
|
|
expected: expected{
|
|
canonical: "/path?gnu=notunix",
|
|
clean: "/?redirect=%2Fpath%3Fgnu%3Dnotunix",
|
|
},
|
|
},
|
|
{
|
|
name: "with multiple query parameters",
|
|
url: "/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
expected: expected{
|
|
canonical: "/path?gnu=notunix&foo=bar",
|
|
clean: "/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
},
|
|
},
|
|
{
|
|
name: "relative url with absolute url in redirect",
|
|
url: "/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "/some-path?with=query",
|
|
clean: "/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "with unescaped query parameters",
|
|
url: "/some-path?redirect=/path?gnu=notunix&foo=bar",
|
|
expected: expected{
|
|
canonical: "/path?gnu=notunix",
|
|
clean: "/some-path?redirect=/path?gnu=notunix&foo=bar",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with different domain",
|
|
url: "http://not-wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "/path",
|
|
clean: "/",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with context path",
|
|
url: "http://wonderwall/some-path?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "/path",
|
|
clean: "/some-path",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with query parameters",
|
|
url: "http://wonderwall/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
expected: expected{
|
|
canonical: "/path?gnu=notunix&foo=bar",
|
|
clean: "/some-path",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with subdomain",
|
|
url: "http://app.wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "/path",
|
|
clean: "/",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with absolute url in redirect",
|
|
url: "http://wonderwall/?redirect=http%3A%2F%2Fwonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "/some-path?with=query",
|
|
clean: "/",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with different domain in redirect",
|
|
url: "http://wonderwall/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "/some-path?with=query",
|
|
clean: "/",
|
|
},
|
|
},
|
|
{
|
|
name: "relative url with fragment in redirect",
|
|
url: "/?redirect=%2F%23%2Fsome-path",
|
|
expected: expected{
|
|
canonical: "/#/some-path",
|
|
clean: "/?redirect=%2F%23%2Fsome-path",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with fragment in redirect",
|
|
url: "/?redirect=http%3A%2F%2Fwonderwall%2F%23%2Fsome-path",
|
|
expected: expected{
|
|
canonical: "/#/some-path",
|
|
clean: "/?redirect=http%3A%2F%2Fwonderwall%2F%23%2Fsome-path",
|
|
},
|
|
},
|
|
} {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
r := mock.NewGetRequest(tt.url, ingresses)
|
|
assert.Equal(t, tt.expected.canonical, h.Canonical(r))
|
|
assert.Equal(t, tt.expected.clean, h.Clean(r, tt.url))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSSOServer(t *testing.T) {
|
|
cfg := mock.Config()
|
|
cfg.Ingresses = []string{
|
|
"http://wonderwall",
|
|
"http://wonderwall/some-path",
|
|
}
|
|
cfg.SSO.Enabled = true
|
|
cfg.SSO.Domain = "wonderwall"
|
|
cfg.SSO.ServerDefaultRedirectURL = "http://fallback.wonderwall"
|
|
ingresses := mock.Ingresses(cfg)
|
|
|
|
h, err := url.NewSSOServerRedirect(cfg)
|
|
require.NoError(t, err)
|
|
|
|
for _, tt := range []struct {
|
|
name string
|
|
url string
|
|
expected expected
|
|
}{
|
|
{
|
|
name: "no redirect param",
|
|
url: "/",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://fallback.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "empty redirect param",
|
|
url: "/?redirect=",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://fallback.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "no redirect param, context path",
|
|
url: "/some-path",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://fallback.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "empty redirect param, context path",
|
|
url: "/some-path?redirect=",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://fallback.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "with query parameters",
|
|
url: "/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://fallback.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "relative url with absolute url in redirect",
|
|
url: "/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://fallback.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "with unescaped query parameters",
|
|
url: "/some-path?redirect=/path?gnu=notunix&foo=bar",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://fallback.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url",
|
|
url: "http://wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://wonderwall/?redirect=%2Fpath",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url, different domain",
|
|
url: "http://not-wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://fallback.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with context path",
|
|
url: "http://wonderwall/some-path?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://wonderwall/some-path?redirect=%2Fpath",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with query parameters",
|
|
url: "http://wonderwall/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://wonderwall/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url, subdomain",
|
|
url: "http://app.wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://app.wonderwall/?redirect=%2Fpath",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url, nested subdomain",
|
|
url: "http://some.app.wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://some.app.wonderwall/?redirect=%2Fpath",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url in redirect",
|
|
url: "http://wonderwall/?redirect=http%3A%2F%2Fwonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://wonderwall/some-path?with=query",
|
|
clean: "http://wonderwall/?redirect=http%3A%2F%2Fwonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with different domain in redirect",
|
|
url: "http://wonderwall/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://fallback.wonderwall",
|
|
clean: "http://wonderwall/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with subdomain in redirect",
|
|
url: "http://wonderwall/?redirect=http%3A%2F%2Fapp.wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/some-path?with=query",
|
|
clean: "http://wonderwall/?redirect=http%3A%2F%2Fapp.wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with nested subdomain in redirect",
|
|
url: "http://wonderwall/?redirect=http%3A%2F%2Fsome.app.wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://some.app.wonderwall/some-path?with=query",
|
|
clean: "http://wonderwall/?redirect=http%3A%2F%2Fsome.app.wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with fragment in redirect",
|
|
url: "http://wonderwall/?redirect=http%3A%2F%2Fwonderwall%2F%23%2Fsome-path",
|
|
expected: expected{
|
|
canonical: "http://wonderwall/#/some-path",
|
|
clean: "http://wonderwall/?redirect=http%3A%2F%2Fwonderwall%2F%23%2Fsome-path",
|
|
},
|
|
},
|
|
} {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
r := mock.NewGetRequest(tt.url, ingresses)
|
|
assert.Equal(t, tt.expected.canonical, h.Canonical(r))
|
|
assert.Equal(t, tt.expected.clean, h.Clean(r, tt.url))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSSOProxy(t *testing.T) {
|
|
cfg := mock.Config()
|
|
cfg.Ingresses = []string{
|
|
"http://app.wonderwall",
|
|
}
|
|
cfg.SSO.Enabled = true
|
|
cfg.SSO.ServerURL = "http://sso.wonderwall"
|
|
ingresses := mock.Ingresses(cfg)
|
|
|
|
h := url.NewSSOProxyRedirect(ingresses)
|
|
|
|
for _, tt := range []struct {
|
|
name string
|
|
url string
|
|
expected expected
|
|
}{
|
|
{
|
|
name: "no redirect param",
|
|
url: "/",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "empty redirect param",
|
|
url: "/?redirect=",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "no redirect param, context path",
|
|
url: "/some-path",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "empty redirect param, context path",
|
|
url: "/some-path?redirect=",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "with query parameters",
|
|
url: "/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/path?gnu=notunix&foo=bar",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "relative url with absolute url in redirect",
|
|
url: "/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/some-path?with=query",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "with unescaped query parameters",
|
|
url: "/some-path?redirect=/path?gnu=notunix&foo=bar",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/path?gnu=notunix",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url",
|
|
url: "http://app.wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/path",
|
|
clean: "http://app.wonderwall/?redirect=%2Fpath",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url, different domain",
|
|
url: "http://not-wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/path",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with context path",
|
|
url: "http://app.wonderwall/some-path?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/path",
|
|
clean: "http://app.wonderwall/some-path?redirect=%2Fpath",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with query parameters",
|
|
url: "http://app.wonderwall/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/path?gnu=notunix",
|
|
clean: "http://app.wonderwall/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with multiple query parameters",
|
|
url: "http://app.wonderwall/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/path?gnu=notunix&foo=bar",
|
|
clean: "http://app.wonderwall/some-path?redirect=%2Fpath%3Fgnu%3Dnotunix%26foo%3Dbar",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url, different subdomain",
|
|
url: "http://another-app.wonderwall/?redirect=%2Fpath",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/path",
|
|
clean: "http://app.wonderwall",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url in redirect",
|
|
url: "http://app.wonderwall/path?redirect=http%3A%2F%2Fwonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/some-path?with=query",
|
|
clean: "http://app.wonderwall/path?redirect=http%3A%2F%2Fwonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with different domain in redirect",
|
|
url: "http://app.wonderwall/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/some-path?with=query",
|
|
clean: "http://app.wonderwall/?redirect=http%3A%2F%2Fnot-wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with subdomain in redirect",
|
|
url: "http://app.wonderwall/?redirect=http%3A%2F%2Fanother-app.wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/some-path?with=query",
|
|
clean: "http://app.wonderwall/?redirect=http%3A%2F%2Fanother-app.wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with nested subdomain in redirect",
|
|
url: "http://app.wonderwall/?redirect=http%3A%2F%2Fsome.app.wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/some-path?with=query",
|
|
clean: "http://app.wonderwall/?redirect=http%3A%2F%2Fsome.app.wonderwall%2Fsome-path%3Fwith%3Dquery",
|
|
},
|
|
},
|
|
{
|
|
name: "relative url with fragment in redirect",
|
|
url: "http://app.wonderwall/?redirect=%2F%23%2Fsome-path",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/#/some-path",
|
|
clean: "http://app.wonderwall/?redirect=%2F%23%2Fsome-path",
|
|
},
|
|
},
|
|
{
|
|
name: "absolute url with fragment in redirect",
|
|
url: "http://app.wonderwall/?redirect=http%3A%2F%2Fwonderwall%2F%23%2Fsome-path",
|
|
expected: expected{
|
|
canonical: "http://app.wonderwall/#/some-path",
|
|
clean: "http://app.wonderwall/?redirect=http%3A%2F%2Fwonderwall%2F%23%2Fsome-path",
|
|
},
|
|
},
|
|
} {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
r := mock.NewGetRequest(tt.url, ingresses)
|
|
assert.Equal(t, tt.expected.canonical, h.Canonical(r))
|
|
assert.Equal(t, tt.expected.clean, h.Clean(r, tt.url))
|
|
})
|
|
}
|
|
}
|