Compare commits

...
Sign in to create a new pull request.

5 commits

6 changed files with 50 additions and 30 deletions

View file

@ -14,6 +14,13 @@ var ServeFlags = []cli.Flag{
EnvVars: []string{"PAGES_DOMAIN"}, EnvVars: []string{"PAGES_DOMAIN"},
Value: "codeberg.page", 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. // GiteaRoot specifies the root URL of the Gitea instance, without a trailing slash.
&cli.StringFlag{ &cli.StringFlag{
Name: "gitea-root", Name: "gitea-root",

View file

@ -48,6 +48,7 @@ func Serve(ctx *cli.Context) error {
giteaAPIToken := ctx.String("gitea-api-token") giteaAPIToken := ctx.String("gitea-api-token")
rawDomain := ctx.String("raw-domain") rawDomain := ctx.String("raw-domain")
mainDomainSuffix := []byte(ctx.String("pages-domain")) mainDomainSuffix := []byte(ctx.String("pages-domain"))
defaultBranches := strings.Split(strings.ReplaceAll(ctx.String("pages-branches"), " ", ""), ",")
rawInfoPage := ctx.String("raw-info-page") rawInfoPage := ctx.String("raw-info-page")
listeningAddress := fmt.Sprintf("%s:%s", ctx.String("host"), ctx.String("port")) listeningAddress := fmt.Sprintf("%s:%s", ctx.String("host"), ctx.String("port"))
enableHTTPServer := ctx.Bool("enable-http-server") enableHTTPServer := ctx.Bool("enable-http-server")
@ -73,6 +74,10 @@ func Serve(ctx *cli.Context) error {
mainDomainSuffix = append([]byte{'.'}, mainDomainSuffix...) mainDomainSuffix = append([]byte{'.'}, mainDomainSuffix...)
} }
if len(defaultBranches) == 0 {
defaultBranches = []string{"pages"}
}
keyCache := cache.NewKeyValueCache() keyCache := cache.NewKeyValueCache()
challengeCache := cache.NewKeyValueCache() challengeCache := cache.NewKeyValueCache()
// canonicalDomainCache stores canonical domains // canonicalDomainCache stores canonical domains
@ -95,7 +100,9 @@ func Serve(ctx *cli.Context) error {
giteaClient, giteaClient,
giteaRoot, rawInfoPage, giteaRoot, rawInfoPage,
BlacklistedPaths, allowedCorsDomains, BlacklistedPaths, allowedCorsDomains,
dnsLookupCache, canonicalDomainCache, branchTimestampCache, fileResponseCache) dnsLookupCache, canonicalDomainCache, branchTimestampCache, fileResponseCache,
defaultBranches,
)
fastServer := server.SetupServer(handler) fastServer := server.SetupServer(handler)
httpServer := server.SetupHTTPACMEChallengeServer(challengeCache) httpServer := server.SetupHTTPACMEChallengeServer(challengeCache)
@ -116,6 +123,7 @@ func Serve(ctx *cli.Context) error {
listener = tls.NewListener(listener, certificates.TLSConfig(mainDomainSuffix, listener = tls.NewListener(listener, certificates.TLSConfig(mainDomainSuffix,
giteaClient, giteaClient,
defaultBranches[0],
dnsProvider, dnsProvider,
acmeUseRateLimits, acmeUseRateLimits,
keyCache, challengeCache, dnsLookupCache, canonicalDomainCache, keyCache, challengeCache, dnsLookupCache, canonicalDomainCache,

View file

@ -38,6 +38,7 @@ import (
// TLSConfig returns the configuration for generating, serving and cleaning up Let's Encrypt certificates. // TLSConfig returns the configuration for generating, serving and cleaning up Let's Encrypt certificates.
func TLSConfig(mainDomainSuffix []byte, func TLSConfig(mainDomainSuffix []byte,
giteaClient *gitea.Client, giteaClient *gitea.Client,
firstDefaultBranch,
dnsProvider string, dnsProvider string,
acmeUseRateLimits bool, acmeUseRateLimits bool,
keyCache, challengeCache, dnsLookupCache, canonicalDomainCache cache.SetGetKey, keyCache, challengeCache, dnsLookupCache, canonicalDomainCache cache.SetGetKey,
@ -75,7 +76,7 @@ func TLSConfig(mainDomainSuffix []byte,
sni = string(sniBytes) sni = string(sniBytes)
} else { } else {
var targetRepo, targetBranch string 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 == "" { if targetOwner == "" {
// DNS not set up, return main certificate to redirect to the docs // DNS not set up, return main certificate to redirect to the docs
sniBytes = mainDomainSuffix sniBytes = mainDomainSuffix

View file

@ -9,7 +9,7 @@ import (
// GetTargetFromDNS searches for CNAME or TXT entries on the request domain ending with MainDomainSuffix. // GetTargetFromDNS searches for CNAME or TXT entries on the request domain ending with MainDomainSuffix.
// If everything is fine, it returns the target data. // 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 // Get CNAME or TXT
var cname string var cname string
var err error var err error
@ -46,10 +46,10 @@ func GetTargetFromDNS(domain, mainDomainSuffix string, dnsLookupCache cache.SetG
targetBranch = cnameParts[len(cnameParts)-3] targetBranch = cnameParts[len(cnameParts)-3]
} }
if targetRepo == "" { if targetRepo == "" {
targetRepo = "pages" targetRepo = firstDefaultBranch
} }
if targetBranch == "" && targetRepo != "pages" { if targetBranch == "" && targetRepo != firstDefaultBranch {
targetBranch = "pages" targetBranch = firstDefaultBranch
} }
// if targetBranch is still empty, the caller must find the default branch // if targetBranch is still empty, the caller must find the default branch
return return

View file

@ -23,6 +23,7 @@ func Handler(mainDomainSuffix, rawDomain []byte,
giteaRoot, rawInfoPage string, giteaRoot, rawInfoPage string,
blacklistedPaths, allowedCorsDomains [][]byte, blacklistedPaths, allowedCorsDomains [][]byte,
dnsLookupCache, canonicalDomainCache, branchTimestampCache, fileResponseCache cache.SetGetKey, dnsLookupCache, canonicalDomainCache, branchTimestampCache, fileResponseCache cache.SetGetKey,
defaultBranches []string,
) func(ctx *fasthttp.RequestCtx) { ) func(ctx *fasthttp.RequestCtx) {
return 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() 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 return
} }
// Check if the first directory is a repo with a "pages" branch for _, branch := range defaultBranches {
// example.codeberg.page/myrepo/index.html // Check if the first directory is a repo with a default branch
// example.codeberg.page/pages/... is not allowed here. // example.codeberg.page/myrepo/index.html
log.Debug().Msg("main domain preparations, now trying with specified repo") // example.codeberg.page/{PAGES_BRANCHE}/... is not allowed here.
if pathElements[0] != "pages" && tryBranch(log, log.Debug().Msg("main domain preparations, now trying with specified repo")
pathElements[0], "pages", pathElements[1:], "") { if pathElements[0] != branch && tryBranch(log,
log.Info().Msg("tryBranch, now trying upstream 5") pathElements[0], branch, pathElements[1:], "") {
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, log.Info().Msg("tryBranch, now trying upstream 5")
targetOptions, targetOwner, targetRepo, targetBranch, targetPath, tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost,
canonicalDomainCache, branchTimestampCache, fileResponseCache) targetOptions, targetOwner, targetRepo, targetBranch, targetPath,
return canonicalDomainCache, branchTimestampCache, fileResponseCache)
} return
}
// Try to use the "pages" repo on its default branch // Try to use the "pages" repo on its default branch
// example.codeberg.page/index.html // example.codeberg.page/index.html
log.Debug().Msg("main domain preparations, now trying with default repo/branch") log.Debug().Msg("main domain preparations, now trying with default repo/branch")
if tryBranch(log, if tryBranch(log,
"pages", "", pathElements, "") { branch, "", pathElements, "") {
log.Info().Msg("tryBranch, now trying upstream 6") log.Info().Msg("tryBranch, now trying upstream 6")
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost,
targetOptions, targetOwner, targetRepo, targetBranch, targetPath, targetOptions, targetOwner, targetRepo, targetBranch, targetPath,
canonicalDomainCache, branchTimestampCache, fileResponseCache) canonicalDomainCache, branchTimestampCache, fileResponseCache)
return return
}
} }
// Couldn't find a valid repo/branch // Couldn't find a valid repo/branch
@ -260,7 +263,7 @@ func Handler(mainDomainSuffix, rawDomain []byte,
trimmedHostStr := string(trimmedHost) trimmedHostStr := string(trimmedHost)
// Serve pages from external domains // 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 == "" { if targetOwner == "" {
html.ReturnErrorPage(ctx, fasthttp.StatusFailedDependency) html.ReturnErrorPage(ctx, fasthttp.StatusFailedDependency)
return return
@ -285,7 +288,7 @@ func Handler(mainDomainSuffix, rawDomain []byte,
return return
} else if canonicalDomain != trimmedHostStr { } else if canonicalDomain != trimmedHostStr {
// only redirect if the target is also a codeberg page! // 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 != "" { if targetOwner != "" {
ctx.Redirect("https://"+canonicalDomain+string(ctx.RequestURI()), fasthttp.StatusTemporaryRedirect) ctx.Redirect("https://"+canonicalDomain+string(ctx.RequestURI()), fasthttp.StatusTemporaryRedirect)
return return

View file

@ -24,6 +24,7 @@ func TestHandlerPerformance(t *testing.T) {
cache.NewKeyValueCache(), cache.NewKeyValueCache(),
cache.NewKeyValueCache(), cache.NewKeyValueCache(),
cache.NewKeyValueCache(), cache.NewKeyValueCache(),
[]string{"pages"},
) )
testCase := func(uri string, status int) { testCase := func(uri string, status int) {