package upstream import ( "strconv" "strings" "time" "codeberg.org/codeberg/pages/server/cache" "codeberg.org/codeberg/pages/server/gitea" "github.com/rs/zerolog/log" ) type Redirect struct { From string To string StatusCode int } // redirectsCacheTimeout specifies the timeout for the redirects cache. var redirectsCacheTimeout = 10 * time.Minute const redirectsConfig = "_redirects" // GetRedirects returns redirects specified in the _redirects file. func (o *Options) GetRedirects(giteaClient *gitea.Client, redirectsCache cache.SetGetKey) []Redirect { var redirects []Redirect // Check for cached redirects if cachedValue, ok := redirectsCache.Get(o.TargetOwner + "/" + o.TargetRepo + "/" + o.TargetBranch); ok { redirects = cachedValue.([]Redirect) } else { // Get _redirects file and parse body, err := giteaClient.GiteaRawContent(o.TargetOwner, o.TargetRepo, o.TargetBranch, redirectsConfig) if err == nil { for _, line := range strings.Split(string(body), "\n") { redirectArr := strings.Fields(line) // Ignore comments and invalid lines if strings.HasPrefix(line, "#") || len(redirectArr) < 2 { continue } // Get redirect status code statusCode := 301 if len(redirectArr) == 3 { statusCode, err = strconv.Atoi(redirectArr[2]) if err != nil { log.Info().Err(err).Msgf("could not read %s of %s/%s", redirectsConfig, o.TargetOwner, o.TargetRepo) } } redirects = append(redirects, Redirect{ From: redirectArr[0], To: redirectArr[1], StatusCode: statusCode, }) } } _ = redirectsCache.Set(o.TargetOwner+"/"+o.TargetRepo+"/"+o.TargetBranch, redirects, redirectsCacheTimeout) } return redirects }