diff --git a/server/handler.go b/server/handler.go index 460875c..c25fa2a 100644 --- a/server/handler.go +++ b/server/handler.go @@ -93,7 +93,7 @@ func Handler(mainDomainSuffix, rawDomain string, // tryBranch checks if a branch exists and populates the target variables. If canonicalLink is non-empty, it will // also disallow search indexing and add a Link header to the canonical URL. // TODO: move into external func to not alert vars indirectly - tryBranch := func(log zerolog.Logger, repo, branch string, _path []string, canonicalLink string) bool { + tryBranch1 := func(log zerolog.Logger, repo, branch string, _path []string, canonicalLink string) bool { if repo == "" { log.Debug().Msg("tryBranch: repo == ''") return false @@ -150,13 +150,14 @@ func Handler(mainDomainSuffix, rawDomain string, // raw.codeberg.org/example/myrepo/@main/index.html if len(pathElements) > 2 && strings.HasPrefix(pathElements[2], "@") { log.Debug().Msg("raw domain preparations, now trying with specified branch") - if tryBranch(log, - targetRepo, pathElements[2][1:], pathElements[3:], + if newRepo, newPath, newBranch, newTimestamp, works := tryBranch2(log, ctx, giteaClient, + targetOwner, targetRepo, pathElements[2][1:], pathElements[3:], giteaRoot+"/"+targetOwner+"/"+targetRepo+"/src/branch/%b/%p", - ) { + ); works { + targetOptions.BranchTimestamp = *newTimestamp log.Debug().Msg("tryBranch, now trying upstream 1") tryUpstream(ctx, giteaClient, mainDomainSuffix, trimmedHost, - targetOptions, targetOwner, targetRepo, targetBranch, targetPath, + targetOptions, targetOwner, newRepo, newBranch, newPath, canonicalDomainCache) return } diff --git a/server/try.go b/server/try.go index 135c1e0..ccad226 100644 --- a/server/try.go +++ b/server/try.go @@ -2,13 +2,16 @@ package server import ( "net/http" + "path" "strings" + "time" "codeberg.org/codeberg/pages/html" "codeberg.org/codeberg/pages/server/cache" "codeberg.org/codeberg/pages/server/context" "codeberg.org/codeberg/pages/server/gitea" "codeberg.org/codeberg/pages/server/upstream" + "github.com/rs/zerolog" ) // tryUpstream forwards the target request to the Gitea API, and shows an error page on failure. @@ -47,3 +50,43 @@ func tryUpstream(ctx *context.Context, giteaClient *gitea.Client, html.ReturnErrorPage(ctx, "", ctx.StatusCode) } } + +func tryBranch2(log zerolog.Logger, ctx *context.Context, giteaClient *gitea.Client, + repoOwner, repoName, branch string, _path []string, canonicalLink string) ( + targetRepo, targetPath, targetBranch string, branchTimestamp *time.Time, + works bool) { + if repoName == "" { + log.Debug().Msg("tryBranch: repo == ''") + return "", "", "", nil, false + } + + // Replace "~" to "/" so we can access branch that contains slash character + // Branch name cannot contain "~" so doing this is okay + branch = strings.ReplaceAll(branch, "~", "/") + + // Check if the branch exists, otherwise treat it as a file path + branchTimestampResult := upstream.GetBranchTimestamp(giteaClient, repoOwner, repoName, branch) + if branchTimestampResult == nil { + log.Debug().Msg("tryBranch: branch doesn't exist") + return "", "", "", nil, false + } + + // Branch exists, use it + targetRepo = repoName + targetPath = path.Join(_path...) + targetBranch = branchTimestampResult.Branch + + branchTimestamp = &branchTimestampResult.Timestamp + + if canonicalLink != "" { + // Hide from search machines & add canonical link + ctx.RespWriter.Header().Set("X-Robots-Tag", "noarchive, noindex") + ctx.RespWriter.Header().Set("Link", + strings.NewReplacer("%b", targetBranch, "%p", targetPath).Replace(canonicalLink)+ + "; rel=\"canonical\"", + ) + } + + log.Debug().Msg("tryBranch: true") + return +}