diff --git a/README b/README index a581e49..fbc2418 100644 --- a/README +++ b/README @@ -78,7 +78,7 @@ The fields are as follows: allowed. This is safe if the server is on the public Internet, but not necessarily so if it is on a private network. - `proxyURL`: if running behind a reverse proxy, this specifies the - address of the proxy. + root URL that will be visible outside the proxy. - `canonicalHost`: the canonical name of the host running the server; this will cause clients to be redirected if they use a different hostname to access the server. diff --git a/group/group.go b/group/group.go index 857ffba..9b4e992 100644 --- a/group/group.go +++ b/group/group.go @@ -917,7 +917,6 @@ func GetConfiguration() (*Configuration, error) { return configuration.configuration, nil } - // called locked func (g *Group) getPasswordPermission(creds ClientCredentials) ([]string, error) { desc := g.description @@ -1051,7 +1050,7 @@ type Status struct { // Status returns a group's status. // Base is the base URL for groups; if omitted, then both the Location and // Endpoint members are omitted from the result. -func (g *Group) Status(authentified bool, base string) Status { +func (g *Group) Status(authentified bool, base *url.URL) Status { desc := g.Description() if desc.Redirect != "" { @@ -1064,28 +1063,25 @@ func (g *Group) Status(authentified bool, base string) Status { } var location, endpoint string - if base != "" { - burl, err := url.Parse(base) - if err == nil { - wss := "wss" - if burl.Scheme == "http" { - wss = "ws" - } - l := url.URL{ - Scheme: burl.Scheme, - Host: burl.Host, - Path: path.Join(burl.Path, g.name) + "/", - } - location = l.String() - e := url.URL{ - Scheme: wss, - Host: burl.Host, - Path: "/ws", - } - endpoint = e.String() - } else { - log.Printf("Couldn't parse base URL %v", base) + if base != nil { + wss := "wss" + if base.Scheme == "http" { + wss = "ws" } + l := url.URL{ + Scheme: base.Scheme, + Host: base.Host, + Path: path.Join( + path.Join(base.Path, "/group/"), + g.Name()) + "/", + } + location = l.String() + e := url.URL{ + Scheme: wss, + Host: base.Host, + Path: path.Join(base.Path, "/ws"), + } + endpoint = e.String() } d := Status{ @@ -1108,7 +1104,7 @@ func (g *Group) Status(authentified bool, base string) Status { return d } -func GetPublic(base string) []Status { +func GetPublic(base *url.URL) []Status { gs := make([]Status, 0) Range(func(g *Group) bool { if g.Description().Public { diff --git a/group/group_test.go b/group/group_test.go index 678a517..ae94f8b 100644 --- a/group/group_test.go +++ b/group/group_test.go @@ -42,7 +42,7 @@ func TestGroup(t *testing.T) { t.Errorf("Expected [], got %v", subs) } - if public := GetPublic(""); len(public) != 1 || public[0].Name != "group/subgroup" { + if public := GetPublic(nil); len(public) != 1 || public[0].Name != "group/subgroup" { t.Errorf("Expected group/subgroup, got %v", public) } } diff --git a/rtpconn/webclient.go b/rtpconn/webclient.go index 6a0dcbc..f3e1cfc 100644 --- a/rtpconn/webclient.go +++ b/rtpconn/webclient.go @@ -1161,7 +1161,7 @@ func handleAction(c *webClient, a any) error { if a.group != "" { g = group.Get(a.group) if g != nil { - s := g.Status(true, "") + s := g.Status(true, nil) status = &s data = g.Data() } @@ -1208,7 +1208,7 @@ func handleAction(c *webClient, a any) error { return errors.New("Permissions changed in no group") } perms := append([]string(nil), c.permissions...) - status := g.Status(true, "") + status := g.Status(true, nil) username := c.username c.write(clientMessage{ Type: "joined", diff --git a/webserver/webserver.go b/webserver/webserver.go index 6635875..1ce65a8 100644 --- a/webserver/webserver.go +++ b/webserver/webserver.go @@ -361,29 +361,44 @@ func groupHandler(w http.ResponseWriter, r *http.Request) { return } - status := g.Status(false, "") + status := g.Status(false, nil) cspHeader(w, status.AuthServer) serveFile(w, r, filepath.Join(StaticRoot, "galene.html")) } -func groupBase(r *http.Request) (string, error) { +func baseURL(r *http.Request) (*url.URL, error) { conf, err := group.GetConfiguration() if err != nil { - return "", err + return nil, err } + var pu *url.URL if conf.ProxyURL != "" { - return url.JoinPath(conf.ProxyURL, "/group/") + pu, err = url.Parse(conf.ProxyURL) + if err != nil { + return nil, err + } } scheme := "https" if r.TLS == nil { scheme = "http" } + host := r.Host + path := "" + if pu != nil { + if pu.Scheme != "" { + scheme = pu.Scheme + } + if pu.Host != "" { + host = pu.Host + } + path = pu.Path + } base := url.URL{ Scheme: scheme, - Host: r.Host, - Path: "/group/", + Host: host, + Path: path, } - return base.String(), nil + return &base, nil } func groupStatusHandler(w http.ResponseWriter, r *http.Request) { @@ -404,9 +419,11 @@ func groupStatusHandler(w http.ResponseWriter, r *http.Request) { return } - base, err := groupBase(r) + base, err := baseURL(r) if err != nil { - httpError(w, err) + log.Printf("Parse ProxyURL: %v", err) + http.Error(w, "Internal server error", + http.StatusInternalServerError) return } d := g.Status(false, base) @@ -422,7 +439,7 @@ func groupStatusHandler(w http.ResponseWriter, r *http.Request) { } func publicHandler(w http.ResponseWriter, r *http.Request) { - base, err := groupBase(r) + base, err := baseURL(r) if err != nil { log.Printf("couldn't determine group base: %v", err) httpError(w, err) diff --git a/webserver/webserver_test.go b/webserver/webserver_test.go index 750c5dd..150c113 100644 --- a/webserver/webserver_test.go +++ b/webserver/webserver_test.go @@ -42,12 +42,18 @@ func TestBase(t *testing.T) { t bool h, res string }{ - {"", true, "a.org", "https://a.org/group/"}, - {"", false, "a.org", "http://a.org/group/"}, - {"https://b.org", true, "a.org", "https://b.org/group/"}, - {"https://b.org", false, "a.org", "https://b.org/group/"}, - {"http://b.org", true, "a.org", "http://b.org/group/"}, - {"http://b.org", false, "a.org", "http://b.org/group/"}, + {"", true, "a.org", "https://a.org"}, + {"", false, "a.org", "http://a.org"}, + {"/base", true, "a.org", "https://a.org/base"}, + {"/base", false, "a.org", "http://a.org/base"}, + {"http:", true, "a.org", "http://a.org"}, + {"https:", false, "a.org", "https://a.org"}, + {"http:/base", true, "a.org", "http://a.org/base"}, + {"https:/base", false, "a.org", "https://a.org/base"}, + {"https://b.org", true, "a.org", "https://b.org"}, + {"https://b.org", false, "a.org", "https://b.org"}, + {"http://b.org", true, "a.org", "http://b.org"}, + {"http://b.org", false, "a.org", "http://b.org"}, } dir := t.TempDir() @@ -75,13 +81,13 @@ func TestBase(t *testing.T) { if v.t { tcs = &tls.ConnectionState{} } - base, err := groupBase(&http.Request{ + base, err := baseURL(&http.Request{ TLS: tcs, Host: v.h, }) - if err != nil || base != v.res { + if err != nil || base.String() != v.res { t.Errorf("Expected %v, got %v (%v)", - v.res, base, err, + v.res, base.String(), err, ) } }