mirror of
https://codeberg.org/Codeberg/pages-server.git
synced 2025-04-19 12:54:24 +02:00
Support multiple canonical-domain-files
This commit is contained in:
parent
2410137438
commit
b2d40c5154
13 changed files with 238 additions and 128 deletions
|
@ -81,11 +81,11 @@ var (
|
|||
Usage: "specifies the domain from which raw repository content shall be served, not set disable raw content hosting",
|
||||
EnvVars: []string{"RAW_DOMAIN"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
&cli.StringSliceFlag{
|
||||
Name: "canonical-domain-file",
|
||||
Usage: "specifies the file from which the canonical domain shall be specified in",
|
||||
EnvVars: []string{"CANONICAL_DOMAIN_FILE"},
|
||||
Value: ".domains",
|
||||
Usage: "specifies the file from which the canonical domain may be specified in. Use this flag multiple times to support multiple different file names, if multiple files exist in a single repository they will be merged.",
|
||||
EnvVars: []string{"CANONICAL_DOMAIN_FILES"},
|
||||
Value: cli.NewStringSlice(".domains"),
|
||||
},
|
||||
|
||||
// #########################
|
||||
|
|
|
@ -9,16 +9,16 @@ type Config struct {
|
|||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Host string `default:"[::]"`
|
||||
Port uint16 `default:"443"`
|
||||
HttpPort uint16 `default:"80"`
|
||||
HttpServerEnabled bool `default:"true"`
|
||||
MainDomain string
|
||||
RawDomain string
|
||||
CanonicalDomainFile string `default:".domains"`
|
||||
PagesBranches []string
|
||||
AllowedCorsDomains []string
|
||||
BlacklistedPaths []string
|
||||
Host string `default:"[::]"`
|
||||
Port uint16 `default:"443"`
|
||||
HttpPort uint16 `default:"80"`
|
||||
HttpServerEnabled bool `default:"true"`
|
||||
MainDomain string
|
||||
RawDomain string
|
||||
CanonicalDomainFiles []string `default:"[\".domains\"]"`
|
||||
PagesBranches []string `default:"[\"main\", \"master\", \"pages\"]"`
|
||||
AllowedCorsDomains []string
|
||||
BlacklistedPaths []string
|
||||
}
|
||||
|
||||
type ForgeConfig struct {
|
||||
|
|
|
@ -20,9 +20,6 @@ func NewDefaultConfig() Config {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
// defaults does not support setting arrays from strings
|
||||
config.Server.PagesBranches = []string{"main", "master", "pages"}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
|
@ -76,7 +73,7 @@ func mergeServerConfig(ctx *cli.Context, config *ServerConfig) {
|
|||
config.RawDomain = ctx.String("raw-domain")
|
||||
}
|
||||
if ctx.IsSet("canonical-domain-file") {
|
||||
config.CanonicalDomainFile = ctx.String("canonical-domain-file")
|
||||
config.CanonicalDomainFiles = ctx.StringSlice("canonical-domain-file")
|
||||
}
|
||||
if ctx.IsSet("pages-branch") {
|
||||
config.PagesBranches = ctx.StringSlice("pages-branch")
|
||||
|
|
|
@ -136,16 +136,16 @@ func TestMergeConfigShouldReplaceAllExistingValuesGivenAllArgsExist(t *testing.T
|
|||
cfg := &Config{
|
||||
LogLevel: "original",
|
||||
Server: ServerConfig{
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFile: "original",
|
||||
PagesBranches: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFiles: []string{"original"},
|
||||
PagesBranches: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
},
|
||||
Forge: ForgeConfig{
|
||||
Root: "original",
|
||||
|
@ -177,16 +177,16 @@ func TestMergeConfigShouldReplaceAllExistingValuesGivenAllArgsExist(t *testing.T
|
|||
expectedConfig := &Config{
|
||||
LogLevel: "changed",
|
||||
Server: ServerConfig{
|
||||
Host: "changed",
|
||||
Port: 8443,
|
||||
HttpPort: 443,
|
||||
HttpServerEnabled: true,
|
||||
MainDomain: "changed",
|
||||
RawDomain: "changed",
|
||||
CanonicalDomainFile: "changed",
|
||||
PagesBranches: []string{"changed"},
|
||||
AllowedCorsDomains: []string{"changed"},
|
||||
BlacklistedPaths: append([]string{"changed"}, ALWAYS_BLACKLISTED_PATHS...),
|
||||
Host: "changed",
|
||||
Port: 8443,
|
||||
HttpPort: 443,
|
||||
HttpServerEnabled: true,
|
||||
MainDomain: "changed",
|
||||
RawDomain: "changed",
|
||||
CanonicalDomainFiles: []string{"changed"},
|
||||
PagesBranches: []string{"changed"},
|
||||
AllowedCorsDomains: []string{"changed"},
|
||||
BlacklistedPaths: append([]string{"changed"}, ALWAYS_BLACKLISTED_PATHS...),
|
||||
},
|
||||
Forge: ForgeConfig{
|
||||
Root: "changed",
|
||||
|
@ -276,29 +276,29 @@ func TestMergeServerConfigShouldReplaceAllExistingValuesGivenAllArgsExist(t *tes
|
|||
t,
|
||||
func(ctx *cli.Context) error {
|
||||
cfg := &ServerConfig{
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFile: "original",
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFiles: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
}
|
||||
|
||||
mergeServerConfig(ctx, cfg)
|
||||
|
||||
expectedConfig := &ServerConfig{
|
||||
Host: "changed",
|
||||
Port: 8443,
|
||||
HttpPort: 443,
|
||||
HttpServerEnabled: true,
|
||||
MainDomain: "changed",
|
||||
RawDomain: "changed",
|
||||
CanonicalDomainFile: "changed",
|
||||
AllowedCorsDomains: fixArrayFromCtx(ctx, "allowed-cors-domains", []string{"changed"}),
|
||||
BlacklistedPaths: fixArrayFromCtx(ctx, "blacklisted-paths", append([]string{"changed"}, ALWAYS_BLACKLISTED_PATHS...)),
|
||||
Host: "changed",
|
||||
Port: 8443,
|
||||
HttpPort: 443,
|
||||
HttpServerEnabled: true,
|
||||
MainDomain: "changed",
|
||||
RawDomain: "changed",
|
||||
CanonicalDomainFiles: fixArrayFromCtx(ctx, "canonical-domain-file", []string{"changed"}),
|
||||
AllowedCorsDomains: fixArrayFromCtx(ctx, "allowed-cors-domains", []string{"changed"}),
|
||||
BlacklistedPaths: fixArrayFromCtx(ctx, "blacklisted-paths", append([]string{"changed"}, ALWAYS_BLACKLISTED_PATHS...)),
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedConfig, cfg)
|
||||
|
@ -332,7 +332,7 @@ func TestMergeServerConfigShouldReplaceOnlyOneValueExistingValueGivenOnlyOneArgE
|
|||
{args: []string{"--enable-http-server"}, callback: func(sc *ServerConfig) { sc.HttpServerEnabled = true }},
|
||||
{args: []string{"--pages-domain", "changed"}, callback: func(sc *ServerConfig) { sc.MainDomain = "changed" }},
|
||||
{args: []string{"--raw-domain", "changed"}, callback: func(sc *ServerConfig) { sc.RawDomain = "changed" }},
|
||||
{args: []string{"--canonical-domain-file", "changed"}, callback: func(sc *ServerConfig) { sc.CanonicalDomainFile = "changed" }},
|
||||
{args: []string{"--canonical-domain-file", "changed"}, callback: func(sc *ServerConfig) { sc.CanonicalDomainFiles = []string{"changed"} }},
|
||||
{args: []string{"--pages-branch", "changed"}, callback: func(sc *ServerConfig) { sc.PagesBranches = []string{"changed"} }},
|
||||
{args: []string{"--allowed-cors-domains", "changed"}, callback: func(sc *ServerConfig) { sc.AllowedCorsDomains = []string{"changed"} }},
|
||||
{args: []string{"--blacklisted-paths", "changed"}, callback: func(sc *ServerConfig) { sc.BlacklistedPaths = []string{"changed"} }},
|
||||
|
@ -343,22 +343,23 @@ func TestMergeServerConfigShouldReplaceOnlyOneValueExistingValueGivenOnlyOneArgE
|
|||
t,
|
||||
func(ctx *cli.Context) error {
|
||||
cfg := ServerConfig{
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFile: "original",
|
||||
PagesBranches: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
Host: "original",
|
||||
Port: 8080,
|
||||
HttpPort: 80,
|
||||
HttpServerEnabled: false,
|
||||
MainDomain: "original",
|
||||
RawDomain: "original",
|
||||
CanonicalDomainFiles: []string{"original"},
|
||||
PagesBranches: []string{"original"},
|
||||
AllowedCorsDomains: []string{"original"},
|
||||
BlacklistedPaths: []string{"original"},
|
||||
}
|
||||
|
||||
expectedConfig := cfg
|
||||
pair.callback(&expectedConfig)
|
||||
expectedConfig.BlacklistedPaths = append(expectedConfig.BlacklistedPaths, ALWAYS_BLACKLISTED_PATHS...)
|
||||
|
||||
expectedConfig.CanonicalDomainFiles = fixArrayFromCtx(ctx, "canonical-domain-file", expectedConfig.CanonicalDomainFiles)
|
||||
expectedConfig.PagesBranches = fixArrayFromCtx(ctx, "pages-branch", expectedConfig.PagesBranches)
|
||||
expectedConfig.AllowedCorsDomains = fixArrayFromCtx(ctx, "allowed-cors-domains", expectedConfig.AllowedCorsDomains)
|
||||
expectedConfig.BlacklistedPaths = fixArrayFromCtx(ctx, "blacklisted-paths", expectedConfig.BlacklistedPaths)
|
||||
|
|
|
@ -32,7 +32,7 @@ func TLSConfig(mainDomainSuffix string,
|
|||
giteaClient *gitea.Client,
|
||||
acmeClient *AcmeClient,
|
||||
firstDefaultBranch string,
|
||||
canonicalDomainConfig string,
|
||||
canonicalDomainConfigs []string,
|
||||
challengeCache, canonicalDomainCache cache.ICache,
|
||||
certDB database.CertDB,
|
||||
noDNS01 bool,
|
||||
|
@ -101,10 +101,10 @@ func TLSConfig(mainDomainSuffix string,
|
|||
TargetRepo: targetRepo,
|
||||
TargetBranch: targetBranch,
|
||||
}
|
||||
_, valid := targetOpt.CheckCanonicalDomain(giteaClient, domain, mainDomainSuffix, canonicalDomainConfig, canonicalDomainCache)
|
||||
_, valid := targetOpt.CheckCanonicalDomain(giteaClient, domain, mainDomainSuffix, canonicalDomainConfigs, canonicalDomainCache)
|
||||
if !valid {
|
||||
// We shouldn't obtain a certificate when we cannot check if the
|
||||
// repository has specified this domain in the `.domains` file.
|
||||
// repository has specified this domain in the specified canonical domain file such as the `.domains` file.
|
||||
mayObtainCert = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func Handler(
|
|||
cfg.MainDomain,
|
||||
trimmedHost,
|
||||
pathElements,
|
||||
cfg.CanonicalDomainFile,
|
||||
cfg.CanonicalDomainFiles,
|
||||
canonicalDomainCache, redirectsCache)
|
||||
} else if strings.HasSuffix(trimmedHost, cfg.MainDomain) {
|
||||
log.Debug().Msg("subdomain request detected")
|
||||
|
@ -101,7 +101,7 @@ func Handler(
|
|||
cfg.PagesBranches,
|
||||
trimmedHost,
|
||||
pathElements,
|
||||
cfg.CanonicalDomainFile,
|
||||
cfg.CanonicalDomainFiles,
|
||||
canonicalDomainCache, redirectsCache)
|
||||
} else {
|
||||
log.Debug().Msg("custom domain request detected")
|
||||
|
@ -110,7 +110,7 @@ func Handler(
|
|||
trimmedHost,
|
||||
pathElements,
|
||||
cfg.PagesBranches[0],
|
||||
cfg.CanonicalDomainFile,
|
||||
cfg.CanonicalDomainFiles,
|
||||
canonicalDomainCache, redirectsCache)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
|
@ -19,7 +20,7 @@ func handleCustomDomain(log zerolog.Logger, ctx *context.Context, giteaClient *g
|
|||
trimmedHost string,
|
||||
pathElements []string,
|
||||
firstDefaultBranch string,
|
||||
canonicalDomainConfig string,
|
||||
canonicalDomainConfigs []string,
|
||||
canonicalDomainCache, redirectsCache cache.ICache,
|
||||
) {
|
||||
// Serve pages from custom domains
|
||||
|
@ -48,9 +49,10 @@ func handleCustomDomain(log zerolog.Logger, ctx *context.Context, giteaClient *g
|
|||
TargetBranch: targetBranch,
|
||||
TargetPath: path.Join(pathParts...),
|
||||
}, canonicalLink); works {
|
||||
canonicalDomain, valid := targetOpt.CheckCanonicalDomain(giteaClient, trimmedHost, mainDomainSuffix, canonicalDomainConfig, canonicalDomainCache)
|
||||
canonicalDomain, valid := targetOpt.CheckCanonicalDomain(giteaClient, trimmedHost, mainDomainSuffix, canonicalDomainConfigs, canonicalDomainCache)
|
||||
if !valid {
|
||||
html.ReturnErrorPage(ctx, "domain not specified in <code>.domains</code> file", http.StatusMisdirectedRequest)
|
||||
msg := fmt.Sprintf("canonical domain not specified, files checked: <code>%s</code>", strings.Join(canonicalDomainConfigs, "</code>, <code>"))
|
||||
html.ReturnErrorPage(ctx, msg, http.StatusMisdirectedRequest)
|
||||
return
|
||||
} else if canonicalDomain != trimmedHost {
|
||||
// only redirect if the target is also a codeberg page!
|
||||
|
@ -65,7 +67,7 @@ func handleCustomDomain(log zerolog.Logger, ctx *context.Context, giteaClient *g
|
|||
}
|
||||
|
||||
log.Debug().Msg("tryBranch, now trying upstream 7")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfig, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ func handleRaw(log zerolog.Logger, ctx *context.Context, giteaClient *gitea.Clie
|
|||
mainDomainSuffix string,
|
||||
trimmedHost string,
|
||||
pathElements []string,
|
||||
canonicalDomainConfig string,
|
||||
canonicalDomainConfigs []string,
|
||||
canonicalDomainCache, redirectsCache cache.ICache,
|
||||
) {
|
||||
// Serve raw content from RawDomain
|
||||
|
@ -46,7 +46,7 @@ func handleRaw(log zerolog.Logger, ctx *context.Context, giteaClient *gitea.Clie
|
|||
TargetPath: path.Join(pathElements[3:]...),
|
||||
}, true); works {
|
||||
log.Trace().Msg("tryUpstream: serve raw domain with specified branch")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfig, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
log.Debug().Msg("missing branch info")
|
||||
|
@ -63,7 +63,7 @@ func handleRaw(log zerolog.Logger, ctx *context.Context, giteaClient *gitea.Clie
|
|||
TargetPath: path.Join(pathElements[2:]...),
|
||||
}, true); works {
|
||||
log.Trace().Msg("tryUpstream: serve raw domain with default branch")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfig, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
} else {
|
||||
html.ReturnErrorPage(ctx,
|
||||
fmt.Sprintf("raw domain could not find repo <code>%s/%s</code> or repo is empty", targetOpt.TargetOwner, targetOpt.TargetRepo),
|
||||
|
|
|
@ -21,7 +21,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
|||
defaultPagesBranches []string,
|
||||
trimmedHost string,
|
||||
pathElements []string,
|
||||
canonicalDomainConfig string,
|
||||
canonicalDomainConfigs []string,
|
||||
canonicalDomainCache, redirectsCache cache.ICache,
|
||||
) {
|
||||
// Serve pages from subdomains of MainDomainSuffix
|
||||
|
@ -54,7 +54,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
|||
TargetPath: path.Join(pathElements[2:]...),
|
||||
}, true); works {
|
||||
log.Trace().Msg("tryUpstream: serve with specified repo and branch")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfig, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
} else {
|
||||
html.ReturnErrorPage(
|
||||
ctx,
|
||||
|
@ -86,7 +86,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
|||
TargetPath: path.Join(pathElements[1:]...),
|
||||
}, true); works {
|
||||
log.Trace().Msg("tryUpstream: serve default pages repo with specified branch")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfig, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
} else {
|
||||
html.ReturnErrorPage(
|
||||
ctx,
|
||||
|
@ -111,7 +111,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
|||
TargetPath: path.Join(pathElements[1:]...),
|
||||
}, false); works {
|
||||
log.Debug().Msg("tryBranch, now trying upstream 5")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfig, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
|||
TargetPath: path.Join(pathElements...),
|
||||
}, false); works {
|
||||
log.Debug().Msg("tryBranch, now trying upstream 6")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfig, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ func handleSubDomain(log zerolog.Logger, ctx *context.Context, giteaClient *gite
|
|||
TargetPath: path.Join(pathElements...),
|
||||
}, false); works {
|
||||
log.Debug().Msg("tryBranch, now trying upstream 6")
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfig, canonicalDomainCache, redirectsCache)
|
||||
tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, targetOpt, canonicalDomainConfigs, canonicalDomainCache, redirectsCache)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -18,13 +18,13 @@ import (
|
|||
func tryUpstream(ctx *context.Context, giteaClient *gitea.Client,
|
||||
mainDomainSuffix, trimmedHost string,
|
||||
options *upstream.Options,
|
||||
canonicalDomainConfig string,
|
||||
canonicalDomainConfigs []string,
|
||||
canonicalDomainCache cache.ICache,
|
||||
redirectsCache cache.ICache,
|
||||
) {
|
||||
// check if a canonical domain exists on a request on MainDomain
|
||||
if strings.HasSuffix(trimmedHost, mainDomainSuffix) && !options.ServeRaw {
|
||||
canonicalDomain, _ := options.CheckCanonicalDomain(giteaClient, "", mainDomainSuffix, canonicalDomainConfig, canonicalDomainCache)
|
||||
canonicalDomain, _ := options.CheckCanonicalDomain(giteaClient, "", mainDomainSuffix, canonicalDomainConfigs, canonicalDomainCache)
|
||||
if !strings.HasSuffix(strings.SplitN(canonicalDomain, "/", 2)[0], mainDomainSuffix) {
|
||||
canonicalPath := ctx.Req.RequestURI
|
||||
if options.TargetRepo != defaultPagesRepo {
|
||||
|
|
|
@ -101,7 +101,7 @@ func Serve(ctx *cli.Context) error {
|
|||
giteaClient,
|
||||
acmeClient,
|
||||
cfg.Server.PagesBranches[0],
|
||||
cfg.Server.CanonicalDomainFile,
|
||||
cfg.Server.CanonicalDomainFiles,
|
||||
challengeCache, canonicalDomainCache,
|
||||
certDB,
|
||||
cfg.ACME.NoDNS01,
|
||||
|
|
|
@ -15,56 +15,91 @@ import (
|
|||
var canonicalDomainCacheTimeout = 15 * time.Minute
|
||||
|
||||
// CheckCanonicalDomain returns the canonical domain specified in the repo (using the `.domains` file).
|
||||
func (o *Options) CheckCanonicalDomain(giteaClient *gitea.Client, actualDomain, mainDomainSuffix, canonicalDomainConfig string, canonicalDomainCache cache.ICache) (domain string, valid bool) {
|
||||
canonicalDomainCacheKey := o.TargetOwner + "/" + o.TargetRepo + "/" + o.TargetBranch + "/" + canonicalDomainConfig
|
||||
func (o *Options) CheckCanonicalDomain(giteaClient *gitea.Client, actualDomain, mainDomainSuffix string, canonicalDomainConfigs []string, canonicalDomainCache cache.ICache) (domain string, valid bool) {
|
||||
canonicalDomainCacheKey := o.TargetOwner + "/" + o.TargetRepo + "/" + o.TargetBranch + "/(" + strings.Join(canonicalDomainConfigs, "|") + ")"
|
||||
|
||||
var domains []string
|
||||
|
||||
// Check if this request is cached.
|
||||
if cachedValue, ok := canonicalDomainCache.Get(canonicalDomainCacheKey); ok {
|
||||
domains := cachedValue.([]string)
|
||||
for _, domain := range domains {
|
||||
if domain == actualDomain {
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return domains[0], valid
|
||||
domains = cachedValue.([]string)
|
||||
} else {
|
||||
// Create cache entry for future invocations.
|
||||
domains = o.canonicalDomainList(giteaClient, mainDomainSuffix, canonicalDomainConfigs)
|
||||
|
||||
// Add result to cache.
|
||||
_ = canonicalDomainCache.Set(canonicalDomainCacheKey, domains, canonicalDomainCacheTimeout)
|
||||
}
|
||||
|
||||
body, err := giteaClient.GiteaRawContent(o.TargetOwner, o.TargetRepo, o.TargetBranch, canonicalDomainConfig)
|
||||
if err != nil && !errors.Is(err, gitea.ErrorNotFound) {
|
||||
log.Error().Err(err).Msgf("could not read %s of %s/%s", canonicalDomainConfig, o.TargetOwner, o.TargetRepo)
|
||||
}
|
||||
|
||||
var domains []string
|
||||
for _, domain := range strings.Split(string(body), "\n") {
|
||||
domain = strings.ToLower(domain)
|
||||
domain = strings.TrimSpace(domain)
|
||||
domain = strings.TrimPrefix(domain, "http://")
|
||||
domain = strings.TrimPrefix(domain, "https://")
|
||||
if domain != "" && !strings.HasPrefix(domain, "#") && !strings.ContainsAny(domain, "\t /") && strings.ContainsRune(domain, '.') {
|
||||
domains = append(domains, domain)
|
||||
}
|
||||
for _, domain := range domains {
|
||||
if domain == actualDomain {
|
||||
valid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Add [owner].[pages-domain] as valid domain.
|
||||
domains = append(domains, o.TargetOwner+mainDomainSuffix)
|
||||
if domains[len(domains)-1] == actualDomain {
|
||||
valid = true
|
||||
}
|
||||
|
||||
// If the target repository isn't called pages, add `/[repository]` to the
|
||||
// previous valid domain.
|
||||
if o.TargetRepo != "" && o.TargetRepo != "pages" {
|
||||
domains[len(domains)-1] += "/" + o.TargetRepo
|
||||
}
|
||||
|
||||
// Add result to cache.
|
||||
_ = canonicalDomainCache.Set(canonicalDomainCacheKey, domains, canonicalDomainCacheTimeout)
|
||||
|
||||
// Return the first domain from the list and return if any of the domains
|
||||
// matched the requested domain.
|
||||
return domains[0], valid
|
||||
}
|
||||
|
||||
// canonicalDomainList returns a list of normalized canonical domains as reported by the repository being served.
|
||||
func (o *Options) canonicalDomainList(giteaClient *gitea.Client, mainDomainSuffix string, canonicalDomainConfigs []string) []string {
|
||||
domainConfigMerge := ""
|
||||
|
||||
for _, canonicalDomainConfig := range canonicalDomainConfigs {
|
||||
body, err := giteaClient.GiteaRawContent(o.TargetOwner, o.TargetRepo, o.TargetBranch, canonicalDomainConfig)
|
||||
if err != nil && !errors.Is(err, gitea.ErrorNotFound) {
|
||||
log.Error().Err(err).Msgf("could not read %s of %s/%s", canonicalDomainConfig, o.TargetOwner, o.TargetRepo)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensures files that don't end with a `\n` don't cause domains to be concatenated when combining files.
|
||||
domainConfigMerge = domainConfigMerge + "\n" + string(body)
|
||||
}
|
||||
|
||||
domains := normalizeDomainEntries(domainConfigMerge)
|
||||
|
||||
// Add [owner].[pages-domain] as valid domain.
|
||||
domains = append(domains, o.pageMainDomain(mainDomainSuffix))
|
||||
|
||||
return domains
|
||||
}
|
||||
|
||||
// pageMainDomain returns the [owner].[pages-domain] domain.
|
||||
func (o *Options) pageMainDomain(mainDomainSuffix string) string {
|
||||
pageMainDomain := o.TargetOwner + mainDomainSuffix
|
||||
|
||||
// If the target repository isn't called pages, add `/[repository]` to the
|
||||
// previous valid domain.
|
||||
if o.TargetRepo != "" && o.TargetRepo != "pages" {
|
||||
pageMainDomain += "/" + o.TargetRepo
|
||||
}
|
||||
|
||||
return pageMainDomain
|
||||
}
|
||||
|
||||
// normalizeDomainEntries returns a list of domains, ill formatted domains are skipped.
|
||||
// domainEntries is a new-line separated list of domains.
|
||||
func normalizeDomainEntries(domainEntries string) []string {
|
||||
domains := []string{}
|
||||
|
||||
for _, domain := range strings.Split(domainEntries, "\n") {
|
||||
domain = strings.ToLower(domain)
|
||||
domain = strings.TrimSpace(domain)
|
||||
domain = strings.TrimPrefix(domain, "http://")
|
||||
domain = strings.TrimPrefix(domain, "https://")
|
||||
|
||||
// Skip blank lines.
|
||||
// Skip commented lines.
|
||||
// Skip poorly formatted lines.
|
||||
// Skip domains without '.'.
|
||||
if domain == "" || strings.HasPrefix(domain, "#") || strings.ContainsAny(domain, "\t /") || !strings.ContainsRune(domain, '.') {
|
||||
continue
|
||||
}
|
||||
|
||||
domains = append(domains, domain)
|
||||
}
|
||||
|
||||
return domains
|
||||
}
|
||||
|
|
75
server/upstream/domains_test.go
Normal file
75
server/upstream/domains_test.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package upstream
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPageMainDomainGeneratesTheExpectedDomain(t *testing.T) {
|
||||
defaultOptions := Options{
|
||||
TargetOwner: "",
|
||||
TargetRepo: "",
|
||||
TargetBranch: "",
|
||||
TargetPath: "",
|
||||
Host: "",
|
||||
TryIndexPages: false,
|
||||
BranchTimestamp: time.Time{},
|
||||
appendTrailingSlash: false,
|
||||
redirectIfExists: "",
|
||||
ServeRaw: false,
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
targetOwner string
|
||||
targetRepo string
|
||||
domainSuffix string
|
||||
expectedDomain string
|
||||
}{
|
||||
{"foo", "", ".localhost.mock.directory", "foo.localhost.mock.directory"},
|
||||
{"foo", "pages", ".localhost.mock.directory", "foo.localhost.mock.directory"},
|
||||
{"foo", "bar", ".localhost.mock.directory", "foo.localhost.mock.directory/bar"},
|
||||
} {
|
||||
options := defaultOptions
|
||||
options.TargetOwner = tc.targetOwner
|
||||
options.TargetRepo = tc.targetRepo
|
||||
|
||||
actualDomain := options.pageMainDomain(tc.domainSuffix)
|
||||
|
||||
assert.Equal(t, tc.expectedDomain, actualDomain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeDomainEntries(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
domain string
|
||||
}{
|
||||
{"abc.com"},
|
||||
{"ABC.com"},
|
||||
{" ABC.com"},
|
||||
{"ABC.com "},
|
||||
{" ABC.com "},
|
||||
{"http://ABC.com"},
|
||||
{"https://ABC.com"},
|
||||
} {
|
||||
actualDomains := normalizeDomainEntries(tc.domain)
|
||||
expectedDomains := []string{"abc.com"}
|
||||
|
||||
assert.Equal(t, expectedDomains, actualDomains)
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
domains string
|
||||
expectedDomains []string
|
||||
}{
|
||||
{"", []string{}},
|
||||
{"ABC.com", []string{"abc.com"}},
|
||||
{"ABC.com\nhttps://example.com", []string{"abc.com", "example.com"}},
|
||||
{"\n\nABC.com\n\nhttps://example.com\n", []string{"abc.com", "example.com"}},
|
||||
} {
|
||||
actualDomains := normalizeDomainEntries(tc.domains)
|
||||
|
||||
assert.Equal(t, tc.expectedDomains, actualDomains)
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue