mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-17 12:41:38 +00:00
106 lines
2.6 KiB
Go
106 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
"net/url"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/valyala/fasttemplate"
|
|
)
|
|
|
|
type WildcardPattern struct {
|
|
Domain []string
|
|
CloneURL *fasttemplate.Template
|
|
IndexRepos []*fasttemplate.Template
|
|
FallbackURL *url.URL
|
|
}
|
|
|
|
var wildcardPatterns []*WildcardPattern
|
|
|
|
func (pattern *WildcardPattern) GetHost() string {
|
|
parts := []string{"*"}
|
|
parts = append(parts, pattern.Domain...)
|
|
return strings.Join(parts, ".")
|
|
}
|
|
|
|
// Returns `subdomain, found` where if `found == true`, `subdomain` contains the part of `host`
|
|
// corresponding to the * in the domain pattern.
|
|
func (pattern *WildcardPattern) Matches(host string) (string, bool) {
|
|
hostParts := strings.Split(host, ".")
|
|
if len(hostParts) != 1+len(pattern.Domain) || !slices.Equal(hostParts[1:], pattern.Domain) {
|
|
return "", false
|
|
}
|
|
return hostParts[0], true
|
|
}
|
|
|
|
func (pattern *WildcardPattern) IsFallbackFor(host string) bool {
|
|
if pattern.FallbackURL == nil {
|
|
return false
|
|
}
|
|
_, found := pattern.Matches(host)
|
|
return found
|
|
}
|
|
|
|
func HandleWildcardFallback(w http.ResponseWriter, r *http.Request) (bool, error) {
|
|
host, err := GetHost(r)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
for _, pattern := range wildcardPatterns {
|
|
if pattern.IsFallbackFor(host) {
|
|
log.Printf("proxy: %s via %s", pattern.GetHost(), pattern.FallbackURL)
|
|
|
|
(&httputil.ReverseProxy{
|
|
Rewrite: func(r *httputil.ProxyRequest) {
|
|
r.SetURL(pattern.FallbackURL)
|
|
r.Out.Host = r.In.Host
|
|
r.Out.Header["X-Forwarded-For"] = r.In.Header["X-Forwarded-For"]
|
|
},
|
|
}).ServeHTTP(w, r)
|
|
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func ConfigureWildcards(configs []WildcardConfig) error {
|
|
for _, config := range configs {
|
|
cloneURLTemplate, err := fasttemplate.NewTemplate(config.CloneURL, "<", ">")
|
|
if err != nil {
|
|
return fmt.Errorf("wildcard pattern: clone URL: %w", err)
|
|
}
|
|
|
|
var indexRepoTemplates []*fasttemplate.Template
|
|
for _, indexRepo := range config.IndexRepos {
|
|
indexRepoTemplate, err := fasttemplate.NewTemplate(indexRepo, "<", ">")
|
|
if err != nil {
|
|
return fmt.Errorf("wildcard pattern: index repo: %w", err)
|
|
}
|
|
indexRepoTemplates = append(indexRepoTemplates, indexRepoTemplate)
|
|
}
|
|
|
|
var fallbackURL *url.URL
|
|
if config.FallbackProxyTo != "" {
|
|
fallbackURL, err = url.Parse(config.FallbackProxyTo)
|
|
if err != nil {
|
|
return fmt.Errorf("wildcard pattern: fallback URL: %w", err)
|
|
}
|
|
}
|
|
|
|
wildcardPatterns = append(wildcardPatterns, &WildcardPattern{
|
|
Domain: strings.Split(config.Domain, "."),
|
|
CloneURL: cloneURLTemplate,
|
|
IndexRepos: indexRepoTemplates,
|
|
FallbackURL: fallbackURL,
|
|
})
|
|
}
|
|
return nil
|
|
}
|