[mirror] Scalable static site server for Git forges (like GitHub Pages)
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}