mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-06-02 08:38:17 -04:00
Compare commits
1 commit
main
...
lint-clean
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e88758852 |
10 changed files with 97 additions and 62 deletions
28
.golangci.yml
Normal file
28
.golangci.yml
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
version: "2"
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- gocritic
|
||||||
|
- gocognit
|
||||||
|
- gocyclo
|
||||||
|
- maintidx
|
||||||
|
- dupl
|
||||||
|
- mnd
|
||||||
|
- unparam
|
||||||
|
- ireturn
|
||||||
|
- goconst
|
||||||
|
- errcheck
|
||||||
|
settings:
|
||||||
|
goconst:
|
||||||
|
min-len: 4
|
||||||
|
min-occurrences: 5
|
||||||
|
ignore-tests: true
|
||||||
|
ignore-string-values:
|
||||||
|
- "^[a-z]+$"
|
||||||
|
exclusions:
|
||||||
|
rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- goconst
|
||||||
|
- dupl
|
||||||
|
- mnd
|
||||||
|
|
@ -294,10 +294,10 @@ func Default() *Config {
|
||||||
Gradle: GradleConfig{
|
Gradle: GradleConfig{
|
||||||
BuildCache: GradleBuildCacheConfig{
|
BuildCache: GradleBuildCacheConfig{
|
||||||
ReadOnly: false,
|
ReadOnly: false,
|
||||||
MaxUploadSize: "100MB",
|
MaxUploadSize: defaultGradleMaxUploadSizeStr,
|
||||||
MaxAge: "168h",
|
MaxAge: "168h",
|
||||||
MaxSize: "",
|
MaxSize: "",
|
||||||
SweepInterval: "10m",
|
SweepInterval: defaultGradleSweepIntervalStr,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -481,51 +481,59 @@ func (c *Config) Validate() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate Gradle build cache upload size (always required and must be > 0).
|
if err := c.Gradle.BuildCache.Validate(); err != nil {
|
||||||
if c.Gradle.BuildCache.MaxUploadSize == "" {
|
return err
|
||||||
c.Gradle.BuildCache.MaxUploadSize = "100MB"
|
|
||||||
}
|
}
|
||||||
uploadSize, err := ParseSize(c.Gradle.BuildCache.MaxUploadSize)
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks Gradle build cache settings, applying the default upload
|
||||||
|
// size if unset.
|
||||||
|
func (g *GradleBuildCacheConfig) Validate() error {
|
||||||
|
if g.MaxUploadSize == "" {
|
||||||
|
g.MaxUploadSize = defaultGradleMaxUploadSizeStr
|
||||||
|
}
|
||||||
|
uploadSize, err := ParseSize(g.MaxUploadSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid gradle.build_cache.max_upload_size: %w", err)
|
return fmt.Errorf("invalid gradle.build_cache.max_upload_size: %w", err)
|
||||||
}
|
}
|
||||||
if uploadSize <= 0 {
|
if uploadSize <= 0 {
|
||||||
return fmt.Errorf("invalid gradle.build_cache.max_upload_size %q: must be > 0", c.Gradle.BuildCache.MaxUploadSize)
|
return fmt.Errorf("invalid gradle.build_cache.max_upload_size %q: must be > 0", g.MaxUploadSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate Gradle max age if specified.
|
if g.MaxAge != "" && g.MaxAge != "0" {
|
||||||
if c.Gradle.BuildCache.MaxAge != "" && c.Gradle.BuildCache.MaxAge != "0" {
|
if _, err := time.ParseDuration(g.MaxAge); err != nil {
|
||||||
if _, err := time.ParseDuration(c.Gradle.BuildCache.MaxAge); err != nil {
|
return fmt.Errorf("invalid gradle.build_cache.max_age %q: %w", g.MaxAge, err)
|
||||||
return fmt.Errorf("invalid gradle.build_cache.max_age %q: %w", c.Gradle.BuildCache.MaxAge, err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate Gradle max size if specified.
|
if g.MaxSize != "" {
|
||||||
if c.Gradle.BuildCache.MaxSize != "" {
|
if _, err := ParseSize(g.MaxSize); err != nil {
|
||||||
if _, err := ParseSize(c.Gradle.BuildCache.MaxSize); err != nil {
|
|
||||||
return fmt.Errorf("invalid gradle.build_cache.max_size: %w", err)
|
return fmt.Errorf("invalid gradle.build_cache.max_size: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate Gradle sweep interval if specified.
|
if g.SweepInterval != "" {
|
||||||
if c.Gradle.BuildCache.SweepInterval != "" {
|
d, err := time.ParseDuration(g.SweepInterval)
|
||||||
d, err := time.ParseDuration(c.Gradle.BuildCache.SweepInterval)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid gradle.build_cache.sweep_interval %q: %w", c.Gradle.BuildCache.SweepInterval, err)
|
return fmt.Errorf("invalid gradle.build_cache.sweep_interval %q: %w", g.SweepInterval, err)
|
||||||
}
|
}
|
||||||
if d <= 0 {
|
if d <= 0 {
|
||||||
return fmt.Errorf("invalid gradle.build_cache.sweep_interval %q: must be > 0", c.Gradle.BuildCache.SweepInterval)
|
return fmt.Errorf("invalid gradle.build_cache.sweep_interval %q: must be > 0", g.SweepInterval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultGradleBuildCacheMaxUploadSize = 100 << 20
|
|
||||||
const defaultGradleBuildCacheSweepInterval = 10 * time.Minute
|
|
||||||
const (
|
const (
|
||||||
defaultMetadataTTL = 5 * time.Minute //nolint:mnd // sensible default
|
defaultMetadataTTL = 5 * time.Minute //nolint:mnd // sensible default
|
||||||
defaultDirectServeTTL = 15 * time.Minute //nolint:mnd // sensible default
|
defaultDirectServeTTL = 15 * time.Minute //nolint:mnd // sensible default
|
||||||
|
defaultGradleBuildCacheMaxUploadSize = 100 << 20
|
||||||
|
defaultGradleBuildCacheSweepInterval = 10 * time.Minute
|
||||||
|
defaultGradleMaxUploadSizeStr = "100MB"
|
||||||
|
defaultGradleSweepIntervalStr = "10m"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseMaxSize returns the maximum cache size in bytes.
|
// ParseMaxSize returns the maximum cache size in bytes.
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,11 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const postgresTimestamp = "TIMESTAMP"
|
const (
|
||||||
|
postgresTimestamp = "TIMESTAMP"
|
||||||
|
sqliteDatetime = "DATETIME"
|
||||||
|
colTypeText = "TEXT"
|
||||||
|
)
|
||||||
|
|
||||||
// Schema for proxy-specific tables. The packages and versions tables
|
// Schema for proxy-specific tables. The packages and versions tables
|
||||||
// are compatible with git-pkgs, allowing the proxy to use an existing
|
// are compatible with git-pkgs, allowing the proxy to use an existing
|
||||||
|
|
@ -369,9 +373,9 @@ func isTableNotFound(err error) bool {
|
||||||
func (db *DB) createMigrationsTable() error {
|
func (db *DB) createMigrationsTable() error {
|
||||||
var ts string
|
var ts string
|
||||||
if db.dialect == DialectPostgres {
|
if db.dialect == DialectPostgres {
|
||||||
ts = "TIMESTAMP"
|
ts = postgresTimestamp
|
||||||
} else {
|
} else {
|
||||||
ts = "DATETIME"
|
ts = sqliteDatetime
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS migrations (
|
query := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS migrations (
|
||||||
|
|
@ -457,12 +461,12 @@ func (db *DB) MigrateSchema() error {
|
||||||
|
|
||||||
func migrateAddPackagesEnrichmentColumns(db *DB) error {
|
func migrateAddPackagesEnrichmentColumns(db *DB) error {
|
||||||
columns := map[string]string{
|
columns := map[string]string{
|
||||||
"registry_url": "TEXT",
|
"registry_url": colTypeText,
|
||||||
"supplier_name": "TEXT",
|
"supplier_name": colTypeText,
|
||||||
"supplier_type": "TEXT",
|
"supplier_type": colTypeText,
|
||||||
"source": "TEXT",
|
"source": colTypeText,
|
||||||
"enriched_at": "DATETIME",
|
"enriched_at": sqliteDatetime,
|
||||||
"vulns_synced_at": "DATETIME",
|
"vulns_synced_at": sqliteDatetime,
|
||||||
}
|
}
|
||||||
|
|
||||||
if db.dialect == DialectPostgres {
|
if db.dialect == DialectPostgres {
|
||||||
|
|
@ -487,10 +491,10 @@ func migrateAddPackagesEnrichmentColumns(db *DB) error {
|
||||||
|
|
||||||
func migrateAddVersionsEnrichmentColumns(db *DB) error {
|
func migrateAddVersionsEnrichmentColumns(db *DB) error {
|
||||||
columns := map[string]string{
|
columns := map[string]string{
|
||||||
"integrity": "TEXT",
|
"integrity": colTypeText,
|
||||||
"yanked": "INTEGER DEFAULT 0",
|
"yanked": "INTEGER DEFAULT 0",
|
||||||
"source": "TEXT",
|
"source": colTypeText,
|
||||||
"enriched_at": "DATETIME",
|
"enriched_at": sqliteDatetime,
|
||||||
}
|
}
|
||||||
|
|
||||||
if db.dialect == DialectPostgres {
|
if db.dialect == DialectPostgres {
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ func (h *CondaHandler) handleRepodata(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, "failed to create request", http.StatusInternalServerError)
|
http.Error(w, "failed to create request", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.Header.Set("Accept-Encoding", "gzip")
|
req.Header.Set(headerAcceptEncoding, "gzip")
|
||||||
|
|
||||||
resp, err := h.proxy.HTTPClient.Do(req)
|
resp, err := h.proxy.HTTPClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -241,5 +241,5 @@ func (h *CondaHandler) proxyCached(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// proxyUpstream forwards a request to Anaconda without caching.
|
// proxyUpstream forwards a request to Anaconda without caching.
|
||||||
func (h *CondaHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) {
|
func (h *CondaHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) {
|
||||||
h.proxy.ProxyUpstream(w, r, h.upstreamURL+r.URL.Path, []string{"Accept-Encoding"})
|
h.proxy.ProxyUpstream(w, r, h.upstreamURL+r.URL.Path, []string{headerAcceptEncoding})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,5 +159,5 @@ func (h *CRANHandler) proxyCached(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// proxyUpstream forwards a request to CRAN without caching.
|
// proxyUpstream forwards a request to CRAN without caching.
|
||||||
func (h *CRANHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) {
|
func (h *CRANHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) {
|
||||||
h.proxy.ProxyUpstream(w, r, h.upstreamURL+r.URL.Path, []string{"Accept-Encoding"})
|
h.proxy.ProxyUpstream(w, r, h.upstreamURL+r.URL.Path, []string{headerAcceptEncoding})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ func (h *GemHandler) fetchCompactIndex(r *http.Request, name string) (*http.Resp
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, hdr := range []string{"Accept", "Accept-Encoding", "If-None-Match", "If-Modified-Since"} {
|
for _, hdr := range []string{"Accept", headerAcceptEncoding, "If-None-Match", "If-Modified-Since"} {
|
||||||
if v := r.Header.Get(hdr); v != "" {
|
if v := r.Header.Get(hdr); v != "" {
|
||||||
req.Header.Set(hdr, v)
|
req.Header.Set(hdr, v)
|
||||||
}
|
}
|
||||||
|
|
@ -311,7 +311,7 @@ func (h *GemHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy relevant headers
|
// Copy relevant headers
|
||||||
for _, h := range []string{"Accept", "Accept-Encoding", "If-None-Match", "If-Modified-Since"} {
|
for _, h := range []string{"Accept", headerAcceptEncoding, "If-None-Match", "If-Modified-Since"} {
|
||||||
if v := r.Header.Get(h); v != "" {
|
if v := r.Header.Get(h); v != "" {
|
||||||
req.Header.Set(h, v)
|
req.Header.Set(h, v)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ func (h *GradleBuildCacheHandler) parseCacheKey(urlPath string) (string, int) {
|
||||||
return "", http.StatusBadRequest
|
return "", http.StatusBadRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyPath == "" || strings.Contains(keyPath, "/") {
|
if strings.Contains(keyPath, "/") {
|
||||||
return "", http.StatusNotFound
|
return "", http.StatusNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ const defaultHTTPTimeout = 30 * time.Second
|
||||||
|
|
||||||
const contentTypeJSON = "application/json"
|
const contentTypeJSON = "application/json"
|
||||||
|
|
||||||
|
const headerAcceptEncoding = "Accept-Encoding"
|
||||||
|
|
||||||
// maxMetadataSize is the maximum size of upstream metadata responses (100 MB).
|
// maxMetadataSize is the maximum size of upstream metadata responses (100 MB).
|
||||||
// Package metadata (e.g. npm with many versions) can be large, but unbounded
|
// Package metadata (e.g. npm with many versions) can be large, but unbounded
|
||||||
// reads risk OOM if an upstream misbehaves.
|
// reads risk OOM if an upstream misbehaves.
|
||||||
|
|
@ -726,7 +728,7 @@ func (p *Proxy) proxyMetadataStream(w http.ResponseWriter, r *http.Request, upst
|
||||||
}
|
}
|
||||||
req.Header.Set("Accept", accept)
|
req.Header.Set("Accept", accept)
|
||||||
|
|
||||||
for _, header := range []string{"Accept-Encoding", "If-Modified-Since", "If-None-Match"} {
|
for _, header := range []string{headerAcceptEncoding, "If-Modified-Since", "If-None-Match"} {
|
||||||
if v := r.Header.Get(header); v != "" {
|
if v := r.Header.Get(header); v != "" {
|
||||||
req.Header.Set(header, v)
|
req.Header.Set(header, v)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ func (h *NuGetHandler) handleRegistration(w http.ResponseWriter, r *http.Request
|
||||||
http.Error(w, "failed to create request", http.StatusInternalServerError)
|
http.Error(w, "failed to create request", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.Header.Set("Accept-Encoding", "gzip")
|
req.Header.Set(headerAcceptEncoding, "gzip")
|
||||||
|
|
||||||
resp, err := h.proxy.HTTPClient.Do(req)
|
resp, err := h.proxy.HTTPClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -338,8 +338,8 @@ func (h *NuGetHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy accept-encoding for compression
|
// Copy accept-encoding for compression
|
||||||
if ae := r.Header.Get("Accept-Encoding"); ae != "" {
|
if ae := r.Header.Get(headerAcceptEncoding); ae != "" {
|
||||||
req.Header.Set("Accept-Encoding", ae)
|
req.Header.Set(headerAcceptEncoding, ae)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := h.proxy.HTTPClient.Do(req)
|
resp, err := h.proxy.HTTPClient.Do(req)
|
||||||
|
|
|
||||||
|
|
@ -81,23 +81,7 @@ func sweepGradleBuildCache(
|
||||||
return 0, 0, nil
|
return 0, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(entries, func(i, j int) bool {
|
sortOldestFirst(entries)
|
||||||
iTime := entries[i].ModTime
|
|
||||||
jTime := entries[j].ModTime
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case iTime.IsZero() && jTime.IsZero():
|
|
||||||
return entries[i].Path < entries[j].Path
|
|
||||||
case iTime.IsZero():
|
|
||||||
return true
|
|
||||||
case jTime.IsZero():
|
|
||||||
return false
|
|
||||||
case iTime.Equal(jTime):
|
|
||||||
return entries[i].Path < entries[j].Path
|
|
||||||
default:
|
|
||||||
return iTime.Before(jTime)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
deletedCount := 0
|
deletedCount := 0
|
||||||
freedBytes := int64(0)
|
freedBytes := int64(0)
|
||||||
|
|
@ -154,3 +138,12 @@ func sweepGradleBuildCache(
|
||||||
|
|
||||||
return deletedCount, freedBytes, nil
|
return deletedCount, freedBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sortOldestFirst(entries []storage.ObjectInfo) {
|
||||||
|
sort.Slice(entries, func(i, j int) bool {
|
||||||
|
if entries[i].ModTime.Equal(entries[j].ModTime) {
|
||||||
|
return entries[i].Path < entries[j].Path
|
||||||
|
}
|
||||||
|
return entries[i].ModTime.Before(entries[j].ModTime)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue