1
Fork 0

Allow proxyURL to contain a path.

We now support or reasonable values for proxyURL, such as "http:"
or "/galene".
This commit is contained in:
Juliusz Chroboczek 2024-02-24 12:09:10 +01:00
parent 6756e7f7cc
commit 29e006037c
6 changed files with 66 additions and 47 deletions

2
README
View File

@ -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.

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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",

View File

@ -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)

View File

@ -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,
)
}
}