package main import ( "encoding/json" "fmt" "os" "strconv" "sync" "time" "code.gitea.io/sdk/gitea" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/recover" "github.com/kpango/glg" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/rs/zerolog/pkgerrors" ) type Channel int const ( Stable Channel = iota Prerelease ) type Attachement struct { User string Repo string Tag string Filename string Channel Channel } type RegionCounter struct { RegionCount map[string]int sync.RWMutex } var giteaURL string func getAttachementURL(attachement Attachement) (string, error) { client, err := gitea.NewClient(giteaURL) if err != nil { return "", fmt.Errorf("Failed to create gitea client: %v") } var release *gitea.Release if attachement.Tag != "" { release, _, err = client.GetReleaseByTag(attachement.User, attachement.Repo, attachement.Tag) if err != nil { return "", fmt.Errorf("Failed to get release by tag: %v") } } else { isPrerelease := false if attachement.Channel == Prerelease { isPrerelease = true } releases, _, err := client.ListReleases(attachement.User, attachement.Repo, gitea.ListReleasesOptions{IsPreRelease: &isPrerelease}) if err != nil { return "", fmt.Errorf("Failed to get releases: %v") } if len(releases) == 0 { return "", fmt.Errorf("no release found") } release = releases[0] } for _, a := range release.Attachments { if a.Name == attachement.Filename { return a.DownloadURL, nil } } return "", fmt.Errorf("no matching attachement found") } func (r *RegionCounter) countRegion(region string) { log.Debug().Msgf("Region %s", region) r.Lock() defer r.Unlock() if region == "" { return } r.RegionCount[region]++ } func main() { zerolog.TimeFieldFormat = time.RFC1123Z consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC1123Z} log.Logger = log.Output(consoleWriter).With().Timestamp().Logger() giteaURL = os.Getenv("GITEA_URL") logLevel, err := strconv.Atoi(os.Getenv("LOG_LEVEL")) if err != nil { logLevel = 1 } log.Logger.Level(zerolog.Level(logLevel)) if log.Logger.GetLevel() == zerolog.DebugLevel { log.Logger = log.Output(consoleWriter).With().Timestamp().Caller().Logger() zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack } regionCounter := &RegionCounter{ RegionCount: make(map[string]int), } app := fiber.New(fiber.Config{ GETOnly: true, ServerHeader: "Fiber", AppName: "Gitea Attachement Proxy", }) app.Use(recover.New()) app.Get("/:user/:repo/releases/download/latest/:name", func(c *fiber.Ctx) error { log.Debug().Msgf("%+v", map[string]string{"user": c.Params("user"), "repo": c.Params("repo"), "name": c.Params("name")}) attachement := Attachement{ User: c.Params("user"), Repo: c.Params("repo"), Filename: c.Params("name"), Channel: Stable, } url, err := getAttachementURL(attachement) if err != nil { glg.Debug(err) c.SendString(err.Error()) c.SendStatus(404) return nil } go regionCounter.countRegion(c.GetReqHeaders()["Fly-Region"]) c.Redirect(url, 307) return nil }) app.Get("/:user/:repo/releases/download/latest\\::channel/:name", func(c *fiber.Ctx) error { log.Debug().Msgf("%+v", map[string]string{"user": c.Params("user"), "repo": c.Params("repo"), "name": c.Params("name"), "channel": c.Params("channel")}) channel := Stable if c.Params("channel") == "prerelease" { channel = Prerelease } attachement := Attachement{ User: c.Params("user"), Repo: c.Params("repo"), Filename: c.Params("name"), Channel: channel, } url, err := getAttachementURL(attachement) if err != nil { glg.Debug(err) c.SendString(err.Error()) c.SendStatus(404) return nil } go regionCounter.countRegion(c.GetReqHeaders()["Fly-Region"]) c.Redirect(url, 307) return nil }) app.Get("/:user/:repo/releases/download/tag\\::tag/:name", func(c *fiber.Ctx) error { log.Debug().Msgf("%+v", map[string]string{"user": c.Params("user"), "repo": c.Params("repo"), "name": c.Params("name"), "tag": c.Params("tag")}) attachement := Attachement{ User: c.Params("user"), Repo: c.Params("repo"), Filename: c.Params("name"), Tag: c.Params("tag"), } url, err := getAttachementURL(attachement) if err != nil { glg.Debug(err) c.SendString(err.Error()) c.SendStatus(404) return nil } go regionCounter.countRegion(c.GetReqHeaders()["Fly-Region"]) c.Redirect(url, 307) return nil }) app.Get("/regions", func(c *fiber.Ctx) error { regionCounter.RLock() defer regionCounter.RUnlock() s, e := json.Marshal(regionCounter.RegionCount) //fmt.Sprintf("%+v", regionCounter.RegionCount) if e != nil { log.Error().Err(e) } log.Debug().Msg(string(s)) return c.JSON(regionCounter.RegionCount) }) log.Error().Err(app.Listen(":8080")) }