Let a test give the handlers the upstream fetcher

handlers.Params gets an optional Fetcher, marked optional for fx. When
the app provides one, the handlers pass it to the image service, whose
Fetcher option already existed for tests, instead of letting it build
its own from the config. pixad provides none, so production builds its
fetcher from the config exactly as before. A new test builds the
handlers in an fx app that provides no fetcher, as pixad does, and
checks that an allowlisted address in blocked_networks is refused with
403, which only the dialer that refuses internal addresses does. The
comment on imgcache.ServiceConfig.FetcherConfig now says that its
AllowHTTP and MaxResponseSize apply even when a fetcher is given.

Model: opus-5-5
This commit is contained in:
2026-10-04 19:27:06 +00:00
parent c0f2783990
commit c615a52746
3 changed files with 73 additions and 2 deletions
+10 -1
View File
@@ -27,6 +27,11 @@ type Params struct {
Healthcheck *healthcheck.Healthcheck
Database *database.Database
Config *config.Config
// Fetcher, when provided, fetches upstream images in place of the
// fetcher the handlers build from the config. Only tests provide one;
// pixad does not.
Fetcher httpfetcher.Fetcher `optional:"true"`
}
// Handlers provides HTTP request handlers.
@@ -35,6 +40,7 @@ type Handlers struct {
hc *healthcheck.Healthcheck
db *database.Database
config *config.Config
fetcher httpfetcher.Fetcher
imgSvc *imgcache.Service
imgCache *imgcache.Cache
sessMgr *session.Manager
@@ -54,6 +60,7 @@ func New(lc fx.Lifecycle, params Params) (*Handlers, error) {
hc: params.Healthcheck,
db: params.Database,
config: params.Config,
fetcher: params.Fetcher,
csrfProtect: csrfProtect,
}
@@ -122,10 +129,12 @@ func (s *Handlers) initImageService() error {
fetcherCfg.MaxConnections = s.config.UpstreamConnections
fetcherCfg.BlockedNetworks = s.config.BlockedNetworks
// Create the service
// Create the service. With no fetcher provided, it builds its own from
// fetcherCfg.
svc, err := imgcache.NewService(&imgcache.ServiceConfig{
Cache: cache,
FetcherConfig: fetcherCfg,
Fetcher: s.fetcher,
SigningKey: s.config.SigningKey,
Allowlist: s.config.AllowlistHosts,
MaxConcurrentProcessing: s.config.MaxConcurrentProcessing,