mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-08-17 09:26:04 +00:00
If an https fallback URL is configured, try TLS for Caddy domain check.
This is added pretty much exclusively for Codeberg Pages v2 migration, but the implementation is generic enough to be useful for other similar setups (if anyone ever has to deal with one...)
This commit is contained in:
+45
-8
@@ -1,16 +1,18 @@
|
||||
package git_pages
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ServeCaddy(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query().Get("domain")
|
||||
if query == "" {
|
||||
domain := r.URL.Query().Get("domain")
|
||||
if domain == "" {
|
||||
http.Error(w, "domain parameter required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -19,21 +21,56 @@ func ServeCaddy(w http.ResponseWriter, r *http.Request) {
|
||||
// While TLS certificates may be provisionsed for IP addresses under special circumstances[^1],
|
||||
// this isn't really what git-pages is designed for, and object store accesses can cost money.
|
||||
// [^1]: https://letsencrypt.org/2025/07/01/issuing-our-first-ip-address-certificate
|
||||
if ip := net.ParseIP(query); ip != nil {
|
||||
log.Println("caddy:", query, 404, "(bare IP)")
|
||||
if ip := net.ParseIP(domain); ip != nil {
|
||||
log.Println("caddy:", domain, 404, "(bare IP)")
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
found, err := backend.CheckDomain(r.Context(), strings.ToLower(query))
|
||||
found, err := backend.CheckDomain(r.Context(), strings.ToLower(domain))
|
||||
if !found {
|
||||
// If we don't serve the domain, but a fallback server does, then we should let our
|
||||
// Caddy instance request a TLS certificate. Otherwise, we'll never have an opportunity
|
||||
// to proxy the request further. (This functionality was originally added for Codeberg
|
||||
// Pages v2, which would under some circumstances return certificates with subjectAltName
|
||||
// not valid for the SNI. Go's TLS stack makes `tls.Dial` return an error for these,
|
||||
// thankfully making it unnecessary to examine X.509 certificates manually here.)
|
||||
for _, wildcardConfig := range config.Wildcard {
|
||||
if wildcardConfig.FallbackProxyTo == "" {
|
||||
continue
|
||||
}
|
||||
fallbackURL, err := url.Parse(wildcardConfig.FallbackProxyTo)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if fallbackURL.Scheme != "https" {
|
||||
continue
|
||||
}
|
||||
connectHost := fallbackURL.Host
|
||||
if fallbackURL.Port() != "" {
|
||||
connectHost += ":" + fallbackURL.Port()
|
||||
} else {
|
||||
connectHost += ":443"
|
||||
}
|
||||
log.Printf("caddy: check TLS %s", fallbackURL)
|
||||
connection, err := tls.Dial("tcp", connectHost, &tls.Config{ServerName: domain})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
connection.Close()
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
log.Println("caddy:", query, 200)
|
||||
log.Println("caddy:", domain, 200)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else if err == nil {
|
||||
log.Println("caddy:", query, 404)
|
||||
log.Println("caddy:", domain, 404)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
} else {
|
||||
log.Println("caddy:", query, 500)
|
||||
log.Println("caddy:", domain, 500)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintln(w, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user