diff --git a/cmd/flags.go b/cmd/flags.go index 8ac09ec..50bf6b3 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -14,6 +14,13 @@ var ServeFlags = []cli.Flag{ EnvVars: []string{"PAGES_DOMAIN"}, Value: "codeberg.page", }, + // Default branches to fetch assets from + &cli.StringFlag{ + Name: "pages-branches", + Usage: "defines branches to fetch assets from", + EnvVars: []string{"PAGES_BRANCHES"}, + Value: "pages", + }, // GiteaRoot specifies the root URL of the Gitea instance, without a trailing slash. &cli.StringFlag{ Name: "gitea-root", diff --git a/cmd/main.go b/cmd/main.go index 41809cb..1830cef 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -48,6 +48,7 @@ func Serve(ctx *cli.Context) error { giteaAPIToken := ctx.String("gitea-api-token") rawDomain := ctx.String("raw-domain") mainDomainSuffix := []byte(ctx.String("pages-domain")) + defaultBranches := strings.Split(strings.ReplaceAll(ctx.String("pages-branches"), " ", ""), ",") rawInfoPage := ctx.String("raw-info-page") listeningAddress := fmt.Sprintf("%s:%s", ctx.String("host"), ctx.String("port")) enableHTTPServer := ctx.Bool("enable-http-server") @@ -73,6 +74,10 @@ func Serve(ctx *cli.Context) error { mainDomainSuffix = append([]byte{'.'}, mainDomainSuffix...) } + if len(defaultBranches) == 0 { + defaultBranches = []string{"pages"} + } + keyCache := cache.NewKeyValueCache() challengeCache := cache.NewKeyValueCache() // canonicalDomainCache stores canonical domains @@ -95,7 +100,9 @@ func Serve(ctx *cli.Context) error { giteaClient, giteaRoot, rawInfoPage, BlacklistedPaths, allowedCorsDomains, - dnsLookupCache, canonicalDomainCache, branchTimestampCache, fileResponseCache) + dnsLookupCache, canonicalDomainCache, branchTimestampCache, fileResponseCache, + defaultBranches, + ) fastServer := server.SetupServer(handler) httpServer := server.SetupHTTPACMEChallengeServer(challengeCache) @@ -116,6 +123,7 @@ func Serve(ctx *cli.Context) error { listener = tls.NewListener(listener, certificates.TLSConfig(mainDomainSuffix, giteaClient, + defaultBranches[0], dnsProvider, acmeUseRateLimits, keyCache, challengeCache, dnsLookupCache, canonicalDomainCache, diff --git a/server/certificates/certificates.go b/server/certificates/certificates.go index 8944468..b1c1329 100644 --- a/server/certificates/certificates.go +++ b/server/certificates/certificates.go @@ -38,6 +38,7 @@ import ( // TLSConfig returns the configuration for generating, serving and cleaning up Let's Encrypt certificates. func TLSConfig(mainDomainSuffix []byte, giteaClient *gitea.Client, + firstDefaultBranch, dnsProvider string, acmeUseRateLimits bool, keyCache, challengeCache, dnsLookupCache, canonicalDomainCache cache.SetGetKey, @@ -75,7 +76,7 @@ func TLSConfig(mainDomainSuffix []byte, sni = string(sniBytes) } else { var targetRepo, targetBranch string - targetOwner, targetRepo, targetBranch = dnsutils.GetTargetFromDNS(sni, string(mainDomainSuffix), dnsLookupCache) + targetOwner, targetRepo, targetBranch = dnsutils.GetTargetFromDNS(sni, string(mainDomainSuffix), firstDefaultBranch, dnsLookupCache) if targetOwner == "" { // DNS not set up, return main certificate to redirect to the docs sniBytes = mainDomainSuffix diff --git a/server/dns/dns.go b/server/dns/dns.go index dc759b0..d30f1e0 100644 --- a/server/dns/dns.go +++ b/server/dns/dns.go @@ -9,7 +9,7 @@ import ( // GetTargetFromDNS searches for CNAME or TXT entries on the request domain ending with MainDomainSuffix. // If everything is fine, it returns the target data. -func GetTargetFromDNS(domain, mainDomainSuffix string, dnsLookupCache cache.SetGetKey) (targetOwner, targetRepo, targetBranch string) { +func GetTargetFromDNS(domain, mainDomainSuffix, firstDefaultBranch string, dnsLookupCache cache.SetGetKey) (targetOwner, targetRepo, targetBranch string) { // Get CNAME or TXT var cname string var err error @@ -46,10 +46,10 @@ func GetTargetFromDNS(domain, mainDomainSuffix string, dnsLookupCache cache.SetG targetBranch = cnameParts[len(cnameParts)-3] } if targetRepo == "" { - targetRepo = "pages" + targetRepo = firstDefaultBranch } - if targetBranch == "" && targetRepo != "pages" { - targetBranch = "pages" + if targetBranch == "" && targetRepo != firstDefaultBranch { + targetBranch = firstDefaultBranch } // if targetBranch is still empty, the caller must find the default branch return diff --git a/server/handler.go b/server/handler.go index cd67aa7..eaa2feb 100644 --- a/server/handler.go +++ b/server/handler.go @@ -23,6 +23,7 @@ func Handler(mainDomainSuffix, rawDomain []byte, giteaRoot, rawInfoPage string, blacklistedPaths, allowedCorsDomains [][]byte, dnsLookupCache, canonicalDomainCache, branchTimestampCache, fileResponseCache cache.SetGetKey, + defaultBranches []string, ) func(ctx *fasthttp.RequestCtx) { return func(ctx *fasthttp.RequestCtx) { log := log.With().Strs("Handler", []string{string(ctx.Request.Host()), string(ctx.Request.Header.RequestURI())}).Logger() @@ -227,29 +228,31 @@ func Handler(mainDomainSuffix, rawDomain []byte, return } - // Check if the first directory is a repo with a "pages" branch - // example.codeberg.page/myrepo/index.html - // example.codeberg.page/pages/... is not allowed here. - log.Debug().Msg("main domain preparations, now trying with specified repo") - if pathElements[0] != "pages" && tryBranch(log, - pathElements[0], "pages", pathElements[1:], "") { - log.Info().Msg("tryBranch, now trying upstream 5") - tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, - targetOptions, targetOwner, targetRepo, targetBranch, targetPath, - canonicalDomainCache, branchTimestampCache, fileResponseCache) - return - } + for _, branch := range defaultBranches { + // Check if the first directory is a repo with a default branch + // example.codeberg.page/myrepo/index.html + // example.codeberg.page/{PAGES_BRANCHE}/... is not allowed here. + log.Debug().Msg("main domain preparations, now trying with specified repo") + if pathElements[0] != branch && tryBranch(log, + pathElements[0], branch, pathElements[1:], "") { + log.Info().Msg("tryBranch, now trying upstream 5") + tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, + targetOptions, targetOwner, targetRepo, targetBranch, targetPath, + canonicalDomainCache, branchTimestampCache, fileResponseCache) + return + } - // Try to use the "pages" repo on its default branch - // example.codeberg.page/index.html - log.Debug().Msg("main domain preparations, now trying with default repo/branch") - if tryBranch(log, - "pages", "", pathElements, "") { - log.Info().Msg("tryBranch, now trying upstream 6") - tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, - targetOptions, targetOwner, targetRepo, targetBranch, targetPath, - canonicalDomainCache, branchTimestampCache, fileResponseCache) - return + // Try to use the "pages" repo on its default branch + // example.codeberg.page/index.html + log.Debug().Msg("main domain preparations, now trying with default repo/branch") + if tryBranch(log, + branch, "", pathElements, "") { + log.Info().Msg("tryBranch, now trying upstream 6") + tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, + targetOptions, targetOwner, targetRepo, targetBranch, targetPath, + canonicalDomainCache, branchTimestampCache, fileResponseCache) + return + } } // Couldn't find a valid repo/branch @@ -260,7 +263,7 @@ func Handler(mainDomainSuffix, rawDomain []byte, trimmedHostStr := string(trimmedHost) // Serve pages from external domains - targetOwner, targetRepo, targetBranch = dns.GetTargetFromDNS(trimmedHostStr, string(mainDomainSuffix), dnsLookupCache) + targetOwner, targetRepo, targetBranch = dns.GetTargetFromDNS(trimmedHostStr, string(mainDomainSuffix), defaultBranches[0], dnsLookupCache) if targetOwner == "" { html.ReturnErrorPage(ctx, fasthttp.StatusFailedDependency) return @@ -285,7 +288,7 @@ func Handler(mainDomainSuffix, rawDomain []byte, return } else if canonicalDomain != trimmedHostStr { // only redirect if the target is also a codeberg page! - targetOwner, _, _ = dns.GetTargetFromDNS(strings.SplitN(canonicalDomain, "/", 2)[0], string(mainDomainSuffix), dnsLookupCache) + targetOwner, _, _ = dns.GetTargetFromDNS(strings.SplitN(canonicalDomain, "/", 2)[0], string(mainDomainSuffix), defaultBranches[0], dnsLookupCache) if targetOwner != "" { ctx.Redirect("https://"+canonicalDomain+string(ctx.RequestURI()), fasthttp.StatusTemporaryRedirect) return diff --git a/server/handler_test.go b/server/handler_test.go index f9a721a..a731ebf 100644 --- a/server/handler_test.go +++ b/server/handler_test.go @@ -24,6 +24,7 @@ func TestHandlerPerformance(t *testing.T) { cache.NewKeyValueCache(), cache.NewKeyValueCache(), cache.NewKeyValueCache(), + []string{"pages"}, ) testCase := func(uri string, status int) {