2820823b36
Add an optional API-key layer to the public read-only API. Keys grant higher per-minute rate limits and attribute usage; anonymous callers are still allowed at a lower IP-based budget. - migration 0008_api_key: api_key table (sha256 hash only, plaintext shown once) - apikey pkg: key generation + hashing - ratelimit pkg: Redis fixed-window limiter + per-key usage counters; fails open - public API middleware: X-API-Key / Bearer auth, X-RateLimit-* headers, 429+Retry-After - admin: issue/list/revoke keys + usage view (API + UI tab) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
43 lines
1.1 KiB
Go
43 lines
1.1 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
)
|
|
|
|
// Config holds runtime configuration for the OpenGoods API server.
|
|
// Values are read from environment variables with sensible defaults so the
|
|
// server can boot in a local Docker Compose setup without extra configuration.
|
|
type Config struct {
|
|
Addr string
|
|
DatabaseURL string
|
|
RedisURL string
|
|
AnonRateLimitPerMin int
|
|
}
|
|
|
|
// Load reads configuration from the environment.
|
|
func Load() Config {
|
|
return Config{
|
|
Addr: getenv("OPENGOODS_ADDR", ":8080"),
|
|
DatabaseURL: getenv("OPENGOODS_DATABASE_URL", "postgres://opengoods:opengoods@localhost:5432/opengoods?sslmode=disable"),
|
|
RedisURL: getenv("OPENGOODS_REDIS_URL", "redis://localhost:6379/0"),
|
|
AnonRateLimitPerMin: getenvInt("OPENGOODS_ANON_RATE_LIMIT_PER_MIN", 60),
|
|
}
|
|
}
|
|
|
|
func getenvInt(key string, fallback int) int {
|
|
if v, ok := os.LookupEnv(key); ok && v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil && n > 0 {
|
|
return n
|
|
}
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getenv(key, fallback string) string {
|
|
if v, ok := os.LookupEnv(key); ok && v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|