diff --git a/server/server.go b/server/server.go index 3263ffe..9a76abd 100755 --- a/server/server.go +++ b/server/server.go @@ -13,8 +13,10 @@ import ( "net/http" "net/url" "regexp" + "slices" "strconv" "strings" + "text/template" "time" "gitea.bel.blue/local/rproxy3/config" @@ -198,9 +200,13 @@ func (s *Server) Pre(foo http.HandlerFunc) http.HandlerFunc { return } - if mapKey(r.Host) == "_" { + switch mapKey(r.Host) { + case "_": s.List(w) return + case "home": + s.Home(w, r) + return } if auth, err := s.lookupAuth(mapKey(r.Host)); err != nil { @@ -285,6 +291,50 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { s.Pre(s.Proxy)(w, r) } +func (s *Server) Home(w http.ResponseWriter, r *http.Request) { + keys := s.db.Keys(nsRouting) + routePrefixes := []string{} + for _, key := range keys { + u, _ := s.lookup(key) + if u != nil && u.String() != "" { + routePrefixes = append(routePrefixes, strings.Split(key, "/")[0]) + } + } + slices.Sort(routePrefixes) + t := strings.ReplaceAll(` + + +
+
+ + {{- $baseDomain := .baseDomain }} + {{- $scheme := .scheme }} + {{- range .routePrefixes }} + {{- $url := printf "%s://%s.%s" $scheme . $baseDomain }} + {{ . }}
+ {{- end }} + + + + `, "\t", " ") + tmpl, err := template.New("home").Parse(t) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "text/html") + if err := tmpl.Execute(w, map[string]any{ + "routePrefixes": routePrefixes, + "domain": r.Host, + "baseDomain": strings.Join(strings.Split(r.Host, ".")[1:], "."), + "scheme": r.URL.Scheme, + }); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + func (s *Server) List(w http.ResponseWriter) { keys := s.db.Keys(nsRouting) hostURL := map[string]string{} diff --git a/server/server_test.go b/server/server_test.go index 8afa025..bd5a998 100755 --- a/server/server_test.go +++ b/server/server_test.go @@ -38,20 +38,39 @@ func TestServerStart(t *testing.T) { } func mockServer() *Server { + s := _mockServer() portServer := httptest.NewServer(nil) - port := strings.Split(portServer.URL, ":")[2] + s.addr = ":" + strings.Split(portServer.URL, ":")[2] portServer.Close() + + return s +} + +func _mockServer() *Server { s := &Server{ db: storage.NewMap(), - addr: ":" + port, limiter: rate.NewLimiter(rate.Limit(50), 50), } if err := s.Routes(); err != nil { panic(fmt.Sprintf("cannot initiate server routes; %v", err)) } + if err := s.Route("test", config.Proxy{To: "http://icanhazip.com"}); err != nil { + panic(err.Error()) + } return s } +func TestServerHome(t *testing.T) { + s := _mockServer() + r := httptest.NewRequest(http.MethodGet, "https://home.int.bel.blue", nil) + w := httptest.NewRecorder() + s.Home(w, r) + if w.Code != http.StatusOK { + t.Fatalf("(%d) %s", w.Code, w.Body.Bytes()) + } + t.Logf("%s", w.Body.Bytes()) +} + func TestServerRoute(t *testing.T) { server := mockServer() p := config.Proxy{