Skip to content

Commit 800ffc6

Browse files
authored
Make Debian upstream repository configurable. (#229)
* Refactor LoadFromEnv to use helpers Avoid triggering the linter about the cyclomatic complexity of the LoadFromEnv function in later changes by refactoring it to use setEnvString/setEnvBool helpers. No functional change, just collapse ~29 repetitive if-blocks into single-line calls to two small helpers. * Make Debian upstream repository configurable Support overriding the Debian handler's upstream (e.g. Ubuntu archives) via PROXY_UPSTREAM_DEBIAN or upstream.debian in the config file. Tested with PROXY_UPSTREAM_DEBIAN=http://archive.ubuntu.com/ubuntu to get Ubuntu Resolute packages.
1 parent 63f0efd commit 800ffc6

7 files changed

Lines changed: 66 additions & 90 deletions

File tree

internal/config/config.go

Lines changed: 50 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ type UpstreamConfig struct {
304304
// Default: https://static.crates.io/crates
305305
CargoDownload string `json:"cargo_download" yaml:"cargo_download"`
306306

307+
// Debian is the upstream APT repository base URL.
308+
// Example: http://archive.ubuntu.com/ubuntu would get Ubuntu.
309+
// Default: http://deb.debian.org/debian
310+
Debian string `json:"debian" yaml:"debian"`
311+
307312
// Auth configures authentication for upstream registries.
308313
// Keys are URL prefixes that are matched against request URLs.
309314
// Example: "https://npm.pkg.github.com" matches all requests to that host.
@@ -378,6 +383,7 @@ func Default() *Config {
378383
GradlePluginPortal: "https://plugins.gradle.org/m2",
379384
Cargo: "https://index.crates.io",
380385
CargoDownload: "https://static.crates.io/crates",
386+
Debian: "http://deb.debian.org/debian",
381387
},
382388
Gradle: GradleConfig{
383389
BuildCache: GradleBuildCacheConfig{
@@ -422,6 +428,21 @@ func Load(path string) (*Config, error) {
422428
return cfg, nil
423429
}
424430

431+
// setEnvString sets *dst from the named environment variable, leaving it
432+
// untouched if the variable is unset or empty.
433+
func setEnvString(dst *string, key string) {
434+
if v := os.Getenv(key); v != "" {
435+
*dst = v
436+
}
437+
}
438+
439+
// setEnvBool is setEnvString for boolean fields, parsed via envBool.
440+
func setEnvBool(dst *bool, key string) {
441+
if v := os.Getenv(key); v != "" {
442+
*dst = envBool(v)
443+
}
444+
}
445+
425446
// LoadFromEnv applies environment variable overrides to a Config.
426447
// Environment variables use the PROXY_ prefix:
427448
// - PROXY_LISTEN
@@ -434,90 +455,35 @@ func Load(path string) (*Config, error) {
434455
// - PROXY_LOG_FORMAT
435456
// - PROXY_HEALTH_STORAGE_PROBE_INTERVAL
436457
func (c *Config) LoadFromEnv() {
437-
if v := os.Getenv("PROXY_LISTEN"); v != "" {
438-
c.Listen = v
439-
}
440-
if v := os.Getenv("PROXY_BASE_URL"); v != "" {
441-
c.BaseURL = v
442-
}
443-
if v := os.Getenv("PROXY_UI_URL"); v != "" {
444-
c.UIBaseURL = v
445-
}
446-
if v := os.Getenv("PROXY_STORAGE_URL"); v != "" {
447-
c.Storage.URL = v
448-
}
449-
if v := os.Getenv("PROXY_STORAGE_PATH"); v != "" {
450-
c.Storage.Path = v
451-
}
452-
if v := os.Getenv("PROXY_STORAGE_MAX_SIZE"); v != "" {
453-
c.Storage.MaxSize = v
454-
}
455-
if v := os.Getenv("PROXY_STORAGE_DIRECT_SERVE"); v != "" {
456-
c.Storage.DirectServe = envBool(v)
457-
}
458-
if v := os.Getenv("PROXY_STORAGE_DIRECT_SERVE_TTL"); v != "" {
459-
c.Storage.DirectServeTTL = v
460-
}
461-
if v := os.Getenv("PROXY_STORAGE_DIRECT_SERVE_BASE_URL"); v != "" {
462-
c.Storage.DirectServeBaseURL = v
463-
}
464-
if v := os.Getenv("PROXY_DATABASE_DRIVER"); v != "" {
465-
c.Database.Driver = v
466-
}
467-
if v := os.Getenv("PROXY_DATABASE_PATH"); v != "" {
468-
c.Database.Path = v
469-
}
470-
if v := os.Getenv("PROXY_DATABASE_URL"); v != "" {
471-
c.Database.URL = v
472-
}
473-
if v := os.Getenv("PROXY_LOG_LEVEL"); v != "" {
474-
c.Log.Level = v
475-
}
476-
if v := os.Getenv("PROXY_LOG_FORMAT"); v != "" {
477-
c.Log.Format = v
478-
}
479-
if v := os.Getenv("PROXY_UPSTREAM_MAVEN"); v != "" {
480-
c.Upstream.Maven = v
481-
}
482-
if v := os.Getenv("PROXY_UPSTREAM_GRADLE_PLUGIN_PORTAL"); v != "" {
483-
c.Upstream.GradlePluginPortal = v
484-
}
485-
if v := os.Getenv("PROXY_COOLDOWN_DEFAULT"); v != "" {
486-
c.Cooldown.Default = v
487-
}
488-
if v := os.Getenv("PROXY_CACHE_METADATA"); v != "" {
489-
c.CacheMetadata = envBool(v)
490-
}
491-
if v := os.Getenv("PROXY_MIRROR_API"); v != "" {
492-
c.MirrorAPI = envBool(v)
493-
}
494-
if v := os.Getenv("PROXY_METADATA_TTL"); v != "" {
495-
c.MetadataTTL = v
496-
}
497-
if v := os.Getenv("PROXY_METADATA_MAX_SIZE"); v != "" {
498-
c.MetadataMaxSize = v
499-
}
500-
if v := os.Getenv("PROXY_HTTP_TIMEOUT"); v != "" {
501-
c.HTTPTimeout = v
502-
}
503-
if v := os.Getenv("PROXY_GRADLE_BUILD_CACHE_READ_ONLY"); v != "" {
504-
c.Gradle.BuildCache.ReadOnly = v == "true" || v == "1"
505-
}
506-
if v := os.Getenv("PROXY_GRADLE_BUILD_CACHE_MAX_UPLOAD_SIZE"); v != "" {
507-
c.Gradle.BuildCache.MaxUploadSize = v
508-
}
509-
if v := os.Getenv("PROXY_GRADLE_BUILD_CACHE_MAX_AGE"); v != "" {
510-
c.Gradle.BuildCache.MaxAge = v
511-
}
512-
if v := os.Getenv("PROXY_GRADLE_BUILD_CACHE_MAX_SIZE"); v != "" {
513-
c.Gradle.BuildCache.MaxSize = v
514-
}
515-
if v := os.Getenv("PROXY_GRADLE_BUILD_CACHE_SWEEP_INTERVAL"); v != "" {
516-
c.Gradle.BuildCache.SweepInterval = v
517-
}
518-
if v := os.Getenv("PROXY_HEALTH_STORAGE_PROBE_INTERVAL"); v != "" {
519-
c.Health.StorageProbeInterval = v
520-
}
458+
setEnvString(&c.Listen, "PROXY_LISTEN")
459+
setEnvString(&c.BaseURL, "PROXY_BASE_URL")
460+
setEnvString(&c.UIBaseURL, "PROXY_UI_URL")
461+
setEnvString(&c.Storage.URL, "PROXY_STORAGE_URL")
462+
setEnvString(&c.Storage.Path, "PROXY_STORAGE_PATH")
463+
setEnvString(&c.Storage.MaxSize, "PROXY_STORAGE_MAX_SIZE")
464+
setEnvBool(&c.Storage.DirectServe, "PROXY_STORAGE_DIRECT_SERVE")
465+
setEnvString(&c.Storage.DirectServeTTL, "PROXY_STORAGE_DIRECT_SERVE_TTL")
466+
setEnvString(&c.Storage.DirectServeBaseURL, "PROXY_STORAGE_DIRECT_SERVE_BASE_URL")
467+
setEnvString(&c.Database.Driver, "PROXY_DATABASE_DRIVER")
468+
setEnvString(&c.Database.Path, "PROXY_DATABASE_PATH")
469+
setEnvString(&c.Database.URL, "PROXY_DATABASE_URL")
470+
setEnvString(&c.Log.Level, "PROXY_LOG_LEVEL")
471+
setEnvString(&c.Log.Format, "PROXY_LOG_FORMAT")
472+
setEnvString(&c.Upstream.Maven, "PROXY_UPSTREAM_MAVEN")
473+
setEnvString(&c.Upstream.GradlePluginPortal, "PROXY_UPSTREAM_GRADLE_PLUGIN_PORTAL")
474+
setEnvString(&c.Upstream.Debian, "PROXY_UPSTREAM_DEBIAN")
475+
setEnvString(&c.Cooldown.Default, "PROXY_COOLDOWN_DEFAULT")
476+
setEnvBool(&c.CacheMetadata, "PROXY_CACHE_METADATA")
477+
setEnvBool(&c.MirrorAPI, "PROXY_MIRROR_API")
478+
setEnvString(&c.MetadataTTL, "PROXY_METADATA_TTL")
479+
setEnvString(&c.MetadataMaxSize, "PROXY_METADATA_MAX_SIZE")
480+
setEnvString(&c.HTTPTimeout, "PROXY_HTTP_TIMEOUT")
481+
setEnvBool(&c.Gradle.BuildCache.ReadOnly, "PROXY_GRADLE_BUILD_CACHE_READ_ONLY")
482+
setEnvString(&c.Gradle.BuildCache.MaxUploadSize, "PROXY_GRADLE_BUILD_CACHE_MAX_UPLOAD_SIZE")
483+
setEnvString(&c.Gradle.BuildCache.MaxAge, "PROXY_GRADLE_BUILD_CACHE_MAX_AGE")
484+
setEnvString(&c.Gradle.BuildCache.MaxSize, "PROXY_GRADLE_BUILD_CACHE_MAX_SIZE")
485+
setEnvString(&c.Gradle.BuildCache.SweepInterval, "PROXY_GRADLE_BUILD_CACHE_SWEEP_INTERVAL")
486+
setEnvString(&c.Health.StorageProbeInterval, "PROXY_HEALTH_STORAGE_PROBE_INTERVAL")
521487
}
522488

523489
// validateAbsoluteURL returns an error if value is not a parseable URL with

internal/config/config_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ func TestDefault(t *testing.T) {
3737
if cfg.Upstream.GradlePluginPortal != "https://plugins.gradle.org/m2" {
3838
t.Errorf("Upstream.GradlePluginPortal = %q, want %q", cfg.Upstream.GradlePluginPortal, "https://plugins.gradle.org/m2")
3939
}
40+
if cfg.Upstream.Debian != "http://deb.debian.org/debian" {
41+
t.Errorf("Upstream.Debian = %q, want %q", cfg.Upstream.Debian, "http://deb.debian.org/debian")
42+
}
4043
}
4144

4245
func TestValidate(t *testing.T) {
@@ -273,6 +276,7 @@ func TestLoadFromEnv(t *testing.T) {
273276
t.Setenv("PROXY_LOG_LEVEL", testLevelDebug)
274277
t.Setenv("PROXY_UPSTREAM_MAVEN", "https://maven.example.com/repository/maven-public")
275278
t.Setenv("PROXY_UPSTREAM_GRADLE_PLUGIN_PORTAL", "https://plugins.example.com/m2")
279+
t.Setenv("PROXY_UPSTREAM_DEBIAN", "http://archive.ubuntu.com/ubuntu")
276280
t.Setenv("PROXY_GRADLE_BUILD_CACHE_READ_ONLY", "true")
277281
t.Setenv("PROXY_GRADLE_BUILD_CACHE_MAX_UPLOAD_SIZE", "32MB")
278282
t.Setenv("PROXY_GRADLE_BUILD_CACHE_MAX_AGE", "12h")
@@ -302,6 +306,9 @@ func TestLoadFromEnv(t *testing.T) {
302306
if cfg.Upstream.GradlePluginPortal != "https://plugins.example.com/m2" {
303307
t.Errorf("Upstream.GradlePluginPortal = %q, want %q", cfg.Upstream.GradlePluginPortal, "https://plugins.example.com/m2")
304308
}
309+
if cfg.Upstream.Debian != "http://archive.ubuntu.com/ubuntu" {
310+
t.Errorf("Upstream.Debian = %q, want %q", cfg.Upstream.Debian, "http://archive.ubuntu.com/ubuntu")
311+
}
305312
if !cfg.Gradle.BuildCache.ReadOnly {
306313
t.Error("Gradle.BuildCache.ReadOnly = false, want true")
307314
}

internal/handler/debian.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ type DebianHandler struct {
2121
}
2222

2323
// NewDebianHandler creates a new Debian/APT protocol handler.
24-
func NewDebianHandler(proxy *Proxy, proxyURL string) *DebianHandler {
24+
func NewDebianHandler(proxy *Proxy, proxyURL string, upstreamURL string) *DebianHandler {
25+
if upstreamURL == "" {
26+
upstreamURL = debianUpstream
27+
}
2528
return &DebianHandler{
2629
proxy: proxy,
27-
upstreamURL: debianUpstream,
30+
upstreamURL: strings.TrimSuffix(upstreamURL, "/"),
2831
proxyURL: strings.TrimSuffix(proxyURL, "/"),
2932
}
3033
}

internal/handler/debian_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ func TestDebianHandler_parsePoolPath(t *testing.T) {
1818
}
1919

2020
func TestDebianHandler_Routes(t *testing.T) {
21-
h := NewDebianHandler(nil, "http://localhost:8080")
21+
h := NewDebianHandler(nil, "http://localhost:8080", "")
2222
assertRoutesBasics(t, h.Routes(), "/dists/stable/Release", "/pool/../../../etc/passwd")
2323
}

internal/handler/download_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ func TestDebianHandler_DownloadCacheMiss(t *testing.T) {
11651165
ContentType: "application/vnd.debian.binary-package",
11661166
}
11671167

1168-
h := NewDebianHandler(proxy, "http://localhost")
1168+
h := NewDebianHandler(proxy, "http://localhost", "")
11691169
srv := httptest.NewServer(h.Routes())
11701170
defer srv.Close()
11711171

internal/handler/notfound_ecosystems_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func TestArtifactDownloadUpstreamNotFoundReturns404(t *testing.T) {
1717
handler func(p *Proxy) http.Handler
1818
}{
1919
{"debian", "/pool/main/n/nginx/nginx_1.18.0-6_amd64.deb",
20-
func(p *Proxy) http.Handler { return NewDebianHandler(p, "http://localhost").Routes() }},
20+
func(p *Proxy) http.Handler { return NewDebianHandler(p, "http://localhost", "").Routes() }},
2121
{"rpm", "/releases/39/Everything/x86_64/os/Packages/n/nginx-1.24.0-1.fc39.x86_64.rpm",
2222
func(p *Proxy) http.Handler { return NewRPMHandler(p, "http://localhost").Routes() }},
2323
{"nuget", "/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg",

internal/server/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ func (s *Server) Start() error {
223223
cranHandler := handler.NewCRANHandler(proxy, s.cfg.BaseURL)
224224
juliaHandler := handler.NewJuliaHandler(proxy, s.cfg.BaseURL)
225225
containerHandler := handler.NewContainerHandler(proxy, s.cfg.BaseURL)
226-
debianHandler := handler.NewDebianHandler(proxy, s.cfg.BaseURL)
226+
debianHandler := handler.NewDebianHandler(proxy, s.cfg.BaseURL, s.cfg.Upstream.Debian)
227227
rpmHandler := handler.NewRPMHandler(proxy, s.cfg.BaseURL)
228228

229229
r.Mount("/npm", http.StripPrefix("/npm", npmHandler.Routes()))

0 commit comments

Comments
 (0)