From e800d2110e8f485cf18aa43209287751d91de2ff Mon Sep 17 00:00:00 2001
From: 6543 <6543@obermui.de>
Date: Thu, 25 Nov 2021 16:12:28 +0100
Subject: [PATCH 1/3] gofmt -s -w *.go */*.go

---
 certificates.go          | 30 +++++++++++++++++-----------
 debug-stepper/stepper.go | 10 +++++-----
 domains.go               | 15 +++++++-------
 handler.go               | 42 +++++++++++++++++++++++-----------------
 handler_test.go          |  1 -
 main.go                  |  4 ++--
 6 files changed, 58 insertions(+), 44 deletions(-)

diff --git a/certificates.go b/certificates.go
index d0735c6..b7c152f 100644
--- a/certificates.go
+++ b/certificates.go
@@ -101,7 +101,7 @@ var tlsConfig = &tls.Config{
 			}
 		}
 
-		err = keyCache.Set(sni, &tlsCertificate, 15 * time.Minute)
+		err = keyCache.Set(sni, &tlsCertificate, 15*time.Minute)
 		if err != nil {
 			panic(err)
 		}
@@ -129,11 +129,11 @@ var tlsConfig = &tls.Config{
 var keyCache = mcache.New()
 var keyDatabase *pogreb.DB
 
-func CheckUserLimit(user string) (error) {
+func CheckUserLimit(user string) error {
 	userLimit, ok := acmeClientCertificateLimitPerUser[user]
 	if !ok {
 		// Each Codeberg user can only add 10 new domains per day.
-		userLimit = equalizer.NewTokenBucket(10, time.Hour * 24)
+		userLimit = equalizer.NewTokenBucket(10, time.Hour*24)
 		acmeClientCertificateLimitPerUser[user] = userLimit
 	}
 	if !userLimit.Ask() {
@@ -149,8 +149,9 @@ type AcmeAccount struct {
 	Email        string
 	Registration *registration.Resource
 	Key          crypto.PrivateKey `json:"-"`
-	KeyPEM       string `json:"Key"`
+	KeyPEM       string            `json:"Key"`
 }
+
 func (u *AcmeAccount) GetEmail() string {
 	return u.Email
 }
@@ -178,14 +179,17 @@ var acmeClientCertificateLimitPerUser = map[string]*equalizer.TokenBucket{}
 
 // rate limit is 300 / 3 hours, we want 200 / 2 hours but to refill more often, so that's 25 new domains every 15 minutes
 // TODO: when this is used a lot, we probably have to think of a somewhat better solution?
-var acmeClientOrderLimit = equalizer.NewTokenBucket(25, 15 * time.Minute)
+var acmeClientOrderLimit = equalizer.NewTokenBucket(25, 15*time.Minute)
 
 // rate limit is 20 / second, we want 10 / second
-var acmeClientRequestLimit = equalizer.NewTokenBucket(10, 1 * time.Second)
+var acmeClientRequestLimit = equalizer.NewTokenBucket(10, 1*time.Second)
 
 var challengeCache = mcache.New()
+
 type AcmeTLSChallengeProvider struct{}
+
 var _ challenge.Provider = AcmeTLSChallengeProvider{}
+
 func (a AcmeTLSChallengeProvider) Present(domain, _, keyAuth string) error {
 	return challengeCache.Set(domain, keyAuth, 1*time.Hour)
 }
@@ -193,10 +197,13 @@ func (a AcmeTLSChallengeProvider) CleanUp(domain, _, _ string) error {
 	challengeCache.Remove(domain)
 	return nil
 }
+
 type AcmeHTTPChallengeProvider struct{}
+
 var _ challenge.Provider = AcmeHTTPChallengeProvider{}
+
 func (a AcmeHTTPChallengeProvider) Present(domain, token, keyAuth string) error {
-	return challengeCache.Set(domain + "/" + token, keyAuth, 1*time.Hour)
+	return challengeCache.Set(domain+"/"+token, keyAuth, 1*time.Hour)
 }
 func (a AcmeHTTPChallengeProvider) CleanUp(domain, token, _ string) error {
 	challengeCache.Remove(domain + "/" + token)
@@ -248,6 +255,7 @@ func retrieveCertFromDB(sni []byte) (tls.Certificate, bool) {
 }
 
 var obtainLocks = sync.Map{}
+
 func obtainCert(acmeClient *lego.Client, domains []string, renew *certificate.Resource, user string) (tls.Certificate, error) {
 	name := strings.TrimPrefix(domains[0], "*")
 	if os.Getenv("DNS_PROVIDER") == "" && len(domains[0]) > 0 && domains[0][0] == '*' {
@@ -356,8 +364,8 @@ func setupCertificates() {
 			panic(err)
 		}
 		myAcmeAccount = AcmeAccount{
-			Email: envOr("ACME_EMAIL", "noreply@example.email"),
-			Key:   privateKey,
+			Email:  envOr("ACME_EMAIL", "noreply@example.email"),
+			Key:    privateKey,
 			KeyPEM: string(certcrypto.PEMEncode(privateKey)),
 		}
 		myAcmeConfig = lego.NewConfig(&myAcmeAccount)
@@ -375,8 +383,8 @@ func setupCertificates() {
 		} else {
 			reg, err := tempClient.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
 				TermsOfServiceAgreed: os.Getenv("ACME_ACCEPT_TERMS") == "true",
-				Kid: os.Getenv("ACME_EAB_KID"),
-				HmacEncoded: os.Getenv("ACME_EAB_HMAC"),
+				Kid:                  os.Getenv("ACME_EAB_KID"),
+				HmacEncoded:          os.Getenv("ACME_EAB_HMAC"),
 			})
 			if err != nil {
 				panic(err)
diff --git a/debug-stepper/stepper.go b/debug-stepper/stepper.go
index 0fd0b6f..05506b6 100644
--- a/debug-stepper/stepper.go
+++ b/debug-stepper/stepper.go
@@ -14,9 +14,9 @@ var Logger = func(s string, i ...interface{}) {
 }
 
 type Stepper struct {
-	Name string
-	Start time.Time
-	LastStep time.Time
+	Name       string
+	Start      time.Time
+	LastStep   time.Time
 	Completion time.Time
 }
 
@@ -27,8 +27,8 @@ func Start(name string) *Stepper {
 	t := time.Now()
 	Logger("%s: started at %s\n", name, t.Format(time.RFC3339))
 	return &Stepper{
-		Name: name,
-		Start: t,
+		Name:     name,
+		Start:    t,
 		LastStep: t,
 	}
 }
diff --git a/domains.go b/domains.go
index 0bf2605..4dcaaee 100644
--- a/domains.go
+++ b/domains.go
@@ -9,7 +9,8 @@ import (
 )
 
 // DnsLookupCacheTimeout specifies the timeout for the DNS lookup cache.
-var DnsLookupCacheTimeout = 15*time.Minute
+var DnsLookupCacheTimeout = 15 * time.Minute
+
 // dnsLookupCache stores DNS lookups for custom domains
 var dnsLookupCache = mcache.New()
 
@@ -61,9 +62,9 @@ func getTargetFromDNS(domain string) (targetOwner, targetRepo, targetBranch stri
 	return
 }
 
-
 // CanonicalDomainCacheTimeout specifies the timeout for the canonical domain cache.
-var CanonicalDomainCacheTimeout = 15*time.Minute
+var CanonicalDomainCacheTimeout = 15 * time.Minute
+
 // canonicalDomainCache stores canonical domains
 var canonicalDomainCache = mcache.New()
 
@@ -98,14 +99,14 @@ func checkCanonicalDomain(targetOwner, targetRepo, targetBranch, actualDomain st
 				}
 			}
 		}
-		domains = append(domains, targetOwner + string(MainDomainSuffix))
-		if domains[len(domains) - 1] == actualDomain {
+		domains = append(domains, targetOwner+string(MainDomainSuffix))
+		if domains[len(domains)-1] == actualDomain {
 			valid = true
 		}
 		if targetRepo != "" && targetRepo != "pages" {
-			domains[len(domains) - 1] += "/" + targetRepo
+			domains[len(domains)-1] += "/" + targetRepo
 		}
-		_ = canonicalDomainCache.Set(targetOwner + "/" + targetRepo + "/" + targetBranch, domains, CanonicalDomainCacheTimeout)
+		_ = canonicalDomainCache.Set(targetOwner+"/"+targetRepo+"/"+targetBranch, domains, CanonicalDomainCacheTimeout)
 	}
 	canonicalDomain = domains[0]
 	return
diff --git a/handler.go b/handler.go
index 5be8a51..53e11cc 100644
--- a/handler.go
+++ b/handler.go
@@ -118,7 +118,7 @@ func handler(ctx *fasthttp.RequestCtx) {
 				if targetRepo != "pages" {
 					canonicalPath = "/" + strings.SplitN(canonicalPath, "/", 3)[2]
 				}
-				ctx.Redirect("https://" + canonicalDomain + canonicalPath, fasthttp.StatusTemporaryRedirect)
+				ctx.Redirect("https://"+canonicalDomain+canonicalPath, fasthttp.StatusTemporaryRedirect)
 				return
 			}
 		}
@@ -185,7 +185,7 @@ func handler(ctx *fasthttp.RequestCtx) {
 		if len(pathElements) > 1 && strings.HasPrefix(pathElements[1], "@") {
 			if targetRepo == "pages" {
 				// example.codeberg.org/pages/@... redirects to example.codeberg.org/@...
-				ctx.Redirect("/" + strings.Join(pathElements[1:], "/"), fasthttp.StatusTemporaryRedirect)
+				ctx.Redirect("/"+strings.Join(pathElements[1:], "/"), fasthttp.StatusTemporaryRedirect)
 				return
 			}
 
@@ -299,30 +299,36 @@ func returnErrorPage(ctx *fasthttp.RequestCtx, code int) {
 }
 
 // BranchExistanceCacheTimeout specifies the timeout for the default branch cache. It can be quite long.
-var DefaultBranchCacheTimeout = 15*time.Minute
+var DefaultBranchCacheTimeout = 15 * time.Minute
+
 // BranchExistanceCacheTimeout specifies the timeout for the branch timestamp & existance cache. It should be shorter
 // than FileCacheTimeout, as that gets invalidated if the branch timestamp has changed. That way, repo changes will be
 // picked up faster, while still allowing the content to be cached longer if nothing changes.
-var BranchExistanceCacheTimeout = 5*time.Minute
+var BranchExistanceCacheTimeout = 5 * time.Minute
+
 // branchTimestampCache stores branch timestamps for faster cache checking
 var branchTimestampCache = mcache.New()
+
 type branchTimestamp struct {
-	branch string
+	branch    string
 	timestamp time.Time
 }
 
 // FileCacheTimeout specifies the timeout for the file content cache - you might want to make this quite long, depending
 // on your available memory.
-var FileCacheTimeout = 5*time.Minute
+var FileCacheTimeout = 5 * time.Minute
+
 // FileCacheSizeLimit limits the maximum file size that will be cached, and is set to 1 MB by default.
 var FileCacheSizeLimit = 1024 * 1024
+
 // fileResponseCache stores responses from the Gitea server
 // TODO: make this an MRU cache with a size limit
 var fileResponseCache = mcache.New()
+
 type fileResponse struct {
-	exists bool
+	exists   bool
 	mimeType string
-	body []byte
+	body     []byte
 }
 
 // getBranchTimestamp finds the default branch (if branch is "") and returns the last modification time of the branch
@@ -339,30 +345,30 @@ func getBranchTimestamp(owner, repo, branch string) *branchTimestamp {
 	if branch == "" {
 		// Get default branch
 		var body = make([]byte, 0)
-		status, body, err := fasthttp.GetTimeout(body, string(GiteaRoot)+"/api/v1/repos/"+owner+"/"+repo, 5 * time.Second)
+		status, body, err := fasthttp.GetTimeout(body, string(GiteaRoot)+"/api/v1/repos/"+owner+"/"+repo, 5*time.Second)
 		if err != nil || status != 200 {
-			_ = branchTimestampCache.Set(owner + "/" + repo + "/" + branch, nil, DefaultBranchCacheTimeout)
+			_ = branchTimestampCache.Set(owner+"/"+repo+"/"+branch, nil, DefaultBranchCacheTimeout)
 			return nil
 		}
 		result.branch = fastjson.GetString(body, "default_branch")
 	}
 
 	var body = make([]byte, 0)
-	status, body, err := fasthttp.GetTimeout(body, string(GiteaRoot)+"/api/v1/repos/"+owner+"/"+repo+"/branches/"+branch, 5 * time.Second)
+	status, body, err := fasthttp.GetTimeout(body, string(GiteaRoot)+"/api/v1/repos/"+owner+"/"+repo+"/branches/"+branch, 5*time.Second)
 	if err != nil || status != 200 {
 		return nil
 	}
 
 	result.timestamp, _ = time.Parse(time.RFC3339, fastjson.GetString(body, "commit", "timestamp"))
-	_ = branchTimestampCache.Set(owner + "/" + repo + "/" + branch, result, BranchExistanceCacheTimeout)
+	_ = branchTimestampCache.Set(owner+"/"+repo+"/"+branch, result, BranchExistanceCacheTimeout)
 	return result
 }
 
 var upstreamClient = fasthttp.Client{
-	ReadTimeout: 10 * time.Second,
-	MaxConnDuration: 60 * time.Second,
+	ReadTimeout:        10 * time.Second,
+	MaxConnDuration:    60 * time.Second,
 	MaxConnWaitTimeout: 1000 * time.Millisecond,
-	MaxConnsPerHost: 128 * 16, // TODO: adjust bottlenecks for best performance with Gitea!
+	MaxConnsPerHost:    128 * 16, // TODO: adjust bottlenecks for best performance with Gitea!
 }
 
 // upstream requests a file from the Gitea API at GiteaRoot and writes it to the request context.
@@ -426,7 +432,7 @@ func upstream(ctx *fasthttp.RequestCtx, targetOwner string, targetRepo string, t
 			optionsForIndexPages.AppendTrailingSlash = true
 			for _, indexPage := range IndexPages {
 				if upstream(ctx, targetOwner, targetRepo, targetBranch, strings.TrimSuffix(targetPath, "/")+"/"+indexPage, &optionsForIndexPages) {
-					_ = fileResponseCache.Set(uri + "?timestamp=" + strconv.FormatInt(options.BranchTimestamp.Unix(), 10), fileResponse{
+					_ = fileResponseCache.Set(uri+"?timestamp="+strconv.FormatInt(options.BranchTimestamp.Unix(), 10), fileResponse{
 						exists: false,
 					}, FileCacheTimeout)
 					return true
@@ -436,7 +442,7 @@ func upstream(ctx *fasthttp.RequestCtx, targetOwner string, targetRepo string, t
 		ctx.Response.SetStatusCode(fasthttp.StatusNotFound)
 		if res != nil {
 			// Update cache if the request is fresh
-			_ = fileResponseCache.Set(uri + "?timestamp=" + strconv.FormatInt(options.BranchTimestamp.Unix(), 10), fileResponse{
+			_ = fileResponseCache.Set(uri+"?timestamp="+strconv.FormatInt(options.BranchTimestamp.Unix(), 10), fileResponse{
 				exists: false,
 			}, FileCacheTimeout)
 		}
@@ -496,7 +502,7 @@ func upstream(ctx *fasthttp.RequestCtx, targetOwner string, targetRepo string, t
 		cachedResponse.exists = true
 		cachedResponse.mimeType = mimeType
 		cachedResponse.body = cacheBodyWriter.Bytes()
-		_ = fileResponseCache.Set(uri + "?timestamp=" + strconv.FormatInt(options.BranchTimestamp.Unix(), 10), cachedResponse, FileCacheTimeout)
+		_ = fileResponseCache.Set(uri+"?timestamp="+strconv.FormatInt(options.BranchTimestamp.Unix(), 10), cachedResponse, FileCacheTimeout)
 	}
 
 	return true
diff --git a/handler_test.go b/handler_test.go
index e7f51e7..70b655e 100644
--- a/handler_test.go
+++ b/handler_test.go
@@ -37,7 +37,6 @@ func TestHandlerPerformance(t *testing.T) {
 		t.Logf("request took %d milliseconds", end.Sub(start).Milliseconds())
 	}
 
-
 	ctx.Response.Reset()
 	ctx.Response.ResetBody()
 	ctx.Request.SetRequestURI("http://example.momar.xyz/")
diff --git a/main.go b/main.go
index 700241a..64f6447 100644
--- a/main.go
+++ b/main.go
@@ -92,7 +92,7 @@ func main() {
 		NoDefaultServerHeader:        true,
 		NoDefaultDate:                true,
 		ReadTimeout:                  30 * time.Second, // needs to be this high for ACME certificates with ZeroSSL & HTTP-01 challenge
-		Concurrency:                  1024 * 32, // TODO: adjust bottlenecks for best performance with Gitea!
+		Concurrency:                  1024 * 32,        // TODO: adjust bottlenecks for best performance with Gitea!
 		MaxConnsPerIP:                100,
 	}
 
@@ -116,7 +116,7 @@ func main() {
 					}
 					ctx.SetBodyString(challenge.(string))
 				} else {
-					ctx.Redirect("https://" + string(ctx.Host()) + string(ctx.RequestURI()), http.StatusMovedPermanently)
+					ctx.Redirect("https://"+string(ctx.Host())+string(ctx.RequestURI()), http.StatusMovedPermanently)
 				}
 			})
 			if err != nil {

From f2bb6aa36faf9df697c54bafadff1bb1fc35330f Mon Sep 17 00:00:00 2001
From: 6543 <6543@obermui.de>
Date: Thu, 25 Nov 2021 16:18:28 +0100
Subject: [PATCH 2/3] fix comment

---
 handler.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/handler.go b/handler.go
index 53e11cc..cbfb958 100644
--- a/handler.go
+++ b/handler.go
@@ -298,7 +298,7 @@ func returnErrorPage(ctx *fasthttp.RequestCtx, code int) {
 	ctx.Response.SetBody(bytes.ReplaceAll(NotFoundPage, []byte("%status"), []byte(strconv.Itoa(code)+" "+message)))
 }
 
-// BranchExistanceCacheTimeout specifies the timeout for the default branch cache. It can be quite long.
+// DefaultBranchCacheTimeout specifies the timeout for the default branch cache. It can be quite long.
 var DefaultBranchCacheTimeout = 15 * time.Minute
 
 // BranchExistanceCacheTimeout specifies the timeout for the branch timestamp & existance cache. It should be shorter

From a6da3eb5f069a1eb2785ed8cf39ec98bc0682595 Mon Sep 17 00:00:00 2001
From: 6543 <6543@obermui.de>
Date: Thu, 25 Nov 2021 16:19:04 +0100
Subject: [PATCH 3/3] ignore vendor/ folder

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index cb42378..3117f77 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
 key-database.pogreb/
 acme-account.json
 build/
+vendor/