Pages apex: on-demand cert and redirect to the forge !47

merged merged by cmc on 2026-08-25 17:05 UTC · krz/gitbay:pages-apex into main

3 files changed, +12 −1

Layout: unified · split

cmd/gitbayd/main.go +3
@@ -184,6 +184,9 @@ func serveCmd() *cobra.Command {
184 return nil 184 return nil
185 } 185 }
186 if pd := cfg.Pages.Domain; pd != "" { 186 if pd := cfg.Pages.Domain; pd != "" {
187 if h == pd {
188 return nil // apex: serves a redirect to the forge
189 }
187 if owner, ok := strings.CutSuffix(h, "."+pd); ok && 190 if owner, ok := strings.CutSuffix(h, "."+pd); ok &&
188 !strings.Contains(owner, ".") && st.OwnerExists(owner) { 191 !strings.Contains(owner, ".") && st.OwnerExists(owner) {
189 return nil 192 return nil
e2e/pages_test.go +4 −1
@@ -107,12 +107,15 @@ func TestPages(t *testing.T) {
107 for _, tc := range []struct{ host, path string }{ 107 for _, tc := range []struct{ host, path string }{
108 {"alice.p.test", "/secret/"}, 108 {"alice.p.test", "/secret/"},
109 {"bob.p.test", "/"}, 109 {"bob.p.test", "/"},
110 {"p.test", "/"},
111 } { 110 } {
112 if resp, _ = inst.pagesGet(t, tc.host, tc.path); resp.StatusCode != 404 { 111 if resp, _ = inst.pagesGet(t, tc.host, tc.path); resp.StatusCode != 404 {
113 t.Fatalf("%s%s: %d, want 404", tc.host, tc.path, resp.StatusCode) 112 t.Fatalf("%s%s: %d, want 404", tc.host, tc.path, resp.StatusCode)
114 } 113 }
115 } 114 }
115 // The apex redirects to the forge.
116 if resp, _ = inst.pagesGet(t, "p.test", "/"); resp.StatusCode != 302 || !strings.Contains(resp.Header.Get("Location"), "gitbay.test") {
117 t.Fatalf("apex: %d -> %s", resp.StatusCode, resp.Header.Get("Location"))
118 }
116 119
117 // The forge itself still answers on its own host. 120 // The forge itself still answers on its own host.
118 if status, _ := inst.get(t, "/explore"); status != 200 { 121 if status, _ := inst.get(t, "/explore"); status != 200 {
internal/httpd/pages.go +5
@@ -46,6 +46,11 @@ func (s *Server) servePage(w http.ResponseWriter, r *http.Request, host string)
46 http.Error(w, "method not allowed", http.StatusMethodNotAllowed) 46 http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
47 return 47 return
48 } 48 }
49 // The apex has no site of its own; send visitors to the forge.
50 if host == s.cfg.Pages.Domain {
51 http.Redirect(w, r, s.cfg.Server.SiteURL, http.StatusFound)
52 return
53 }
49 owner, ok := strings.CutSuffix(host, "."+s.cfg.Pages.Domain) 54 owner, ok := strings.CutSuffix(host, "."+s.cfg.Pages.Domain)
50 if !ok || owner == "" || strings.Contains(owner, ".") { 55 if !ok || owner == "" || strings.Contains(owner, ".") {
51 http.NotFound(w, r) 56 http.NotFound(w, r)