Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
320564ec18 |
|||
|
865cc9f1f6 |
|||
|
3c225c4648 |
|||
|
9c412966fc |
|||
|
dc634287aa |
6 changed files with 50 additions and 30 deletions
|
|
@ -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",
|
||||||
|
|
|
||||||
10
cmd/main.go
10
cmd/main.go
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue