[mirror] Scalable static site server for Git forges (like GitHub Pages)
at main 2.5 kB view raw
1package git_pages 2 3import ( 4 "context" 5 "crypto/tls" 6 "fmt" 7 "net" 8 "net/http" 9 "strings" 10) 11 12func ServeCaddy(w http.ResponseWriter, r *http.Request) { 13 domain := r.URL.Query().Get("domain") 14 if domain == "" { 15 http.Error(w, "domain parameter required", http.StatusBadRequest) 16 return 17 } 18 19 // Save the backend some effort from queries that are essentially guaranteed to fail. 20 // While TLS certificates may be provisionsed for IP addresses under special circumstances[^1], 21 // this isn't really what git-pages is designed for, and object store accesses can cost money. 22 // [^1]: https://letsencrypt.org/2025/07/01/issuing-our-first-ip-address-certificate 23 if ip := net.ParseIP(domain); ip != nil { 24 logc.Println(r.Context(), "caddy:", domain, 404, "(bare IP)") 25 w.WriteHeader(http.StatusNotFound) 26 return 27 } 28 29 found, err := backend.CheckDomain(r.Context(), strings.ToLower(domain)) 30 if !found { 31 // If we don't serve the domain, but a fallback server does, then we should let our 32 // Caddy instance request a TLS certificate. Otherwise, we'll never have an opportunity 33 // to proxy the request further. (This functionality was originally added for Codeberg 34 // Pages v2, which would under some circumstances return certificates with subjectAltName 35 // not valid for the SNI. Go's TLS stack makes `tls.Dial` return an error for these, 36 // thankfully making it unnecessary to examine X.509 certificates manually here.) 37 found, err = tryDialWithSNI(r.Context(), domain) 38 if err != nil { 39 logc.Printf(r.Context(), "caddy err: check SNI: %s\n", err) 40 } 41 } 42 43 if found { 44 logc.Println(r.Context(), "caddy:", domain, 200) 45 w.WriteHeader(http.StatusOK) 46 } else if err == nil { 47 logc.Println(r.Context(), "caddy:", domain, 404) 48 w.WriteHeader(http.StatusNotFound) 49 } else { 50 logc.Println(r.Context(), "caddy:", domain, 500) 51 w.WriteHeader(http.StatusInternalServerError) 52 fmt.Fprintln(w, err) 53 } 54} 55 56func tryDialWithSNI(ctx context.Context, domain string) (bool, error) { 57 if config.Fallback.ProxyTo == nil { 58 return false, nil 59 } 60 61 fallbackURL := config.Fallback.ProxyTo 62 if fallbackURL.Scheme != "https" { 63 return false, nil 64 } 65 66 connectHost := fallbackURL.Host 67 if fallbackURL.Port() != "" { 68 connectHost += ":" + fallbackURL.Port() 69 } else { 70 connectHost += ":443" 71 } 72 73 logc.Printf(ctx, "caddy: check TLS %s", fallbackURL) 74 connection, err := tls.Dial("tcp", connectHost, &tls.Config{ServerName: domain}) 75 if err != nil { 76 return false, err 77 } 78 connection.Close() 79 return true, nil 80}