forked from Nixius/authelia
1
0
Fork 0
ATLAS/docker/ss-atlas/internal/handlers/instance.go

66 lines
1.7 KiB
Go

package handlers
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"regexp"
"strings"
"github.com/go-chi/chi/v5"
)
// instanceUsernamePattern matches valid instance slugs.
var instanceUsernamePattern = regexp.MustCompile(`^[a-z0-9-]+$`)
// handleInstanceProxy enforces account ownership for /i/<slug>, then
// reverse-proxies to that customer stack's web service.
func (a *App) handleInstanceProxy(w http.ResponseWriter, r *http.Request) {
slug := chi.URLParam(r, "username")
if slug == "" {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
if !instanceUsernamePattern.MatchString(slug) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
acct, identity, err := a.currentAccount(r)
if err != nil || acct == nil {
http.Redirect(w, r, a.cfg.IdentityURL, http.StatusSeeOther)
return
}
inst, err := a.accounts.InstanceBySlug(r.Context(), slug)
if err != nil || inst.AccountID != acct.ID {
log.Printf("instance proxy: denied %s access to /i/%s", accountDisplay(acct, identity), slug)
http.Error(w, "forbidden", http.StatusForbidden)
return
}
backendHost := fmt.Sprintf("web.%s", inst.StackName)
backendURL := &url.URL{
Scheme: "http",
Host: backendHost + ":3001",
Path: "/",
}
prefix := "/i/" + slug
pathSuffix := strings.TrimPrefix(r.URL.Path, prefix)
if pathSuffix == "" {
pathSuffix = "/"
}
if !strings.HasPrefix(pathSuffix, "/") {
pathSuffix = "/" + pathSuffix
}
proxy := httputil.NewSingleHostReverseProxy(backendURL)
proxy.Director = func(req *http.Request) {
req.URL.Scheme = backendURL.Scheme
req.URL.Host = backendURL.Host
req.URL.Path = pathSuffix
req.Host = backendURL.Host
}
proxy.ServeHTTP(w, r)
}