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] 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 {