Wire up image handler endpoint with service orchestration

- Add image proxy config options (signing_key, whitelist_hosts, allow_http)
- Create Service to orchestrate cache, fetcher, and processor
- Initialize image service in handlers OnStart hook
- Implement HandleImage with URL parsing, signature validation, cache
- Implement HandleRobotsTxt for search engine prevention
- Parse query params for signature, quality, and fit mode
This commit is contained in:
2026-01-08 04:01:53 -08:00
parent 5462c9222c
commit fd2d108f9c
5 changed files with 487 additions and 17 deletions

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"git.eeqj.de/sneak/smartconfig"
"go.uber.org/fx"
@@ -35,6 +36,11 @@ type Config struct {
SentryDSN string
StateDir string
DBURL string
// Image proxy settings
SigningKey string // HMAC signing key for URL signatures
WhitelistHosts []string // Hosts that don't require signatures
AllowHTTP bool // Allow non-TLS upstream (testing only)
}
// New creates a new Config instance by loading configuration from file.
@@ -79,6 +85,9 @@ func New(_ fx.Lifecycle, params Params) (*Config, error) {
SentryDSN: getString(sc, "sentry_dsn", ""),
MetricsUsername: getString(sc, "metrics.username", ""),
MetricsPassword: getString(sc, "metrics.password", ""),
SigningKey: getString(sc, "signing_key", ""),
WhitelistHosts: getStringSlice(sc, "whitelist_hosts"),
AllowHTTP: getBool(sc, "allow_http", false),
}
// Build DBURL from StateDir if not explicitly set
@@ -132,3 +141,27 @@ func getBool(sc *smartconfig.Config, key string, defaultVal bool) bool {
return val
}
func getStringSlice(sc *smartconfig.Config, key string) []string {
if sc == nil {
return nil
}
val, err := sc.GetString(key)
if err != nil || val == "" {
return nil
}
// Parse comma-separated values
parts := strings.Split(val, ",")
result := make([]string, 0, len(parts))
for _, part := range parts {
trimmed := strings.TrimSpace(part)
if trimmed != "" {
result = append(result, trimmed)
}
}
return result
}