feat(pages): Add subdomain routing and default config support
Some checks failed
Build and Release / Create Release (push) Has been skipped
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 1m32s
Build and Release / Lint (push) Failing after 1m53s
Build and Release / Build Binaries (arm64, linux) (push) Has been skipped
Build and Release / Build Binaries (amd64, darwin) (push) Has been skipped
Build and Release / Build Binaries (amd64, linux) (push) Has been skipped
Build and Release / Build Binaries (amd64, windows) (push) Has been skipped
Build and Release / Build Binaries (arm64, darwin) (push) Has been skipped
Build and Release / Unit Tests (push) Successful in 1m58s

- Update subdomain parser to use {repo}-{owner}.{domain} format
- Add middleware to intercept Pages subdomain requests
- Generate default config when Pages enabled but no .gitea/landing.yaml
- Pages are public landing pages (accessible even for private repos)

🤖 Generated with Claude Code
This commit is contained in:
David H Friedel Jr 2026-01-11 00:15:21 +00:00
parent 919746c756
commit 69d7c72ba8
3 changed files with 60 additions and 5 deletions

View File

@ -70,15 +70,19 @@ func getRepoFromRequest(ctx *context.Context) (*repo_model.Repository, *pages_mo
return repo, config, nil return repo, config, nil
} }
// Parse subdomain: {repo}.{owner}.pages.{domain} // Parse subdomain: {repo}-{owner}.{domain}
// This is a simplified implementation
parts := strings.Split(host, ".") parts := strings.Split(host, ".")
if len(parts) < 4 { if len(parts) < 2 {
return nil, nil, errors.New("invalid pages subdomain") return nil, nil, errors.New("invalid pages subdomain")
} }
repoName := parts[0] // First part is {repo}-{owner}
ownerName := parts[1] repoOwner := strings.SplitN(parts[0], "-", 2)
if len(repoOwner) != 2 {
return nil, nil, errors.New("invalid pages subdomain format")
}
repoName := repoOwner[0]
ownerName := repoOwner[1]
repo, err = repo_model.GetRepositoryByOwnerAndName(ctx, ownerName, repoName) repo, err = repo_model.GetRepositoryByOwnerAndName(ctx, ownerName, repoName)
if err != nil { if err != nil {

View File

@ -302,6 +302,33 @@ var optSignInFromAnyOrigin = verifyAuthWithOptions(&common.VerifyOptions{Disable
// registerWebRoutes register routes // registerWebRoutes register routes
func registerWebRoutes(m *web.Router) { func registerWebRoutes(m *web.Router) {
// Check for Pages subdomain requests first
m.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
host := req.Host
// Remove port if present
if idx := strings.Index(host, ":"); idx > 0 {
host = host[:idx]
}
// Check if this is a subdomain of our main domain
mainDomain := setting.Domain
if strings.HasSuffix(host, "."+mainDomain) {
subdomain := strings.TrimSuffix(host, "."+mainDomain)
// Skip known subdomains
if subdomain != "" && subdomain != "www" && subdomain != "api" && subdomain != "git" && strings.Contains(subdomain, "-") {
// This looks like a Pages subdomain ({repo}-{owner})
ctx := context.GetWebContext(req.Context())
if ctx != nil {
log.Trace("Pages subdomain request: %s", host)
pages.ServeLandingPage(ctx)
return
}
}
}
next.ServeHTTP(w, req)
})
})
// required to be signed in or signed out // required to be signed in or signed out
reqSignIn := verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: true}) reqSignIn := verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: true})
reqSignOut := verifyAuthWithOptions(&common.VerifyOptions{SignOutRequired: true}) reqSignOut := verifyAuthWithOptions(&common.VerifyOptions{SignOutRequired: true})

View File

@ -44,6 +44,10 @@ func GetPagesConfig(ctx context.Context, repo *repo_model.Repository) (*pages_mo
} }
return &config, nil return &config, nil
} }
// If Pages is enabled but no config file, return a default config
if dbConfig != nil && dbConfig.Enabled {
return getDefaultConfig(repo, string(dbConfig.Template)), nil
}
return nil, err return nil, err
} }
@ -93,6 +97,26 @@ func GetPagesConfig(ctx context.Context, repo *repo_model.Repository) (*pages_mo
} }
// loadConfigFromRepo loads the landing.yaml configuration from the repository // loadConfigFromRepo loads the landing.yaml configuration from the repository
// getDefaultConfig returns a default landing page configuration
func getDefaultConfig(repo *repo_model.Repository, template string) *pages_module.LandingConfig {
if template == "" {
template = "simple"
}
return &pages_module.LandingConfig{
Enabled: true,
Template: template,
Hero: pages_module.HeroConfig{
Title: repo.Name,
Tagline: repo.Description,
},
Branding: pages_module.BrandingConfig{
PrimaryColor: "#4183c4",
},
}
}
func loadConfigFromRepo(ctx context.Context, repo *repo_model.Repository) (*pages_module.LandingConfig, string, error) { func loadConfigFromRepo(ctx context.Context, repo *repo_model.Repository) (*pages_module.LandingConfig, string, error) {
gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())
if err != nil { if err != nil {