Skip to content

Repository files navigation

MediaProxy

MediaProxy 是一个高并发、低内存的 Go HTTP(S) 反向代理,支持按需图片处理和本地磁盘缓存。源站可以是 S3、MinIO、Cloudflare R2、CDN 或任意固定 HTTP(S) 服务。

它不是开放代理:源站只来自启动配置,客户端不能通过请求参数改变 scheme、host 或 endpoint。没有 image 参数时走流式透传;有参数时 best-effort 尝试处理,任何不支持、损坏、超限或处理错误都回退源站原响应。

能力

  • 固定单源或按 Host/path 最长前缀匹配的多源路由;每条路由支持 round-robin、weighted round-robin、random 和 least-connection backend 负载均衡。
  • GET/HEAD、Range、条件请求、重定向抑制、escaped path 和原始 query 保留。
  • 固定回源 Host/请求头、allowlist/denylist、Cookie/Authorization 策略、环境代理开关。
  • Forwarded / X-Forwarded-*、可信代理 CIDR、请求 ID 和 JSON 结构化日志。
  • JPEG、PNG、WebP、GIF、AVIF、HEIC/HEIF 的内容探测和 libvips 处理,支持 resize、crop、rotate、flip、quality、format、EXIF orientation 和可选水印。
  • 内存阈值后临时文件暂存、全局 spool budget、图片/输出/并发限制和可取消处理 semaphore。
  • SHA-256 磁盘缓存、TTL/容量清理、完整性校验、singleflight 和共享目录 flock 生成锁。
  • Bearer token、HMAC signed URL、AWS SigV4、OAuth client credentials、源站 mTLS 和 Qiniu 参数子集兼容。
  • /healthz、/readyz、Prometheus /metrics、受保护 pprof、debug decision、cache purge/prewarm。
  • 多证书 SNI HTTPS ingress 和可选 HTTP 308 重定向。

快速启动

export S3IMGPROXY_ORIGIN_URL=https://origin.example.com
export S3IMGPROXY_ADDR=:8080
./s3imgproxy

请求示例:

GET /photos/a.jpg
GET /photos/a.jpg?image=v1/resize,w_300,h_300,mode_contain
GET /photos/a.jpg?image=v1/resize,w_800/format,webp/q,82

image 只由代理消费,其他 query 参数的顺序和编码保持不变。完整语法见 docs/image-parameter-v1.md。

多源和 SNI

多源使用 S3IMGPROXY_ORIGINS_JSON,例如:

[
  {"name":"images","match_host":"img.example.com","path_prefix":"/","load_balance":"weighted_round_robin","backends":[{"name":"a","url":"https://s3-a.example.com/bucket","weight":2},{"name":"b","url":"https://s3-b.example.com/bucket"}]},
  {"name":"private","match_host":"private.example.com","path_prefix":"/avatars","url":"https://r2.example.com/bucket"}
]

HTTPS 证书使用 S3IMGPROXY_TLS_CERTIFICATES_JSON;列表支持精确 host、一级 wildcard 和默认证书。设置 S3IMGPROXY_HTTP_REDIRECT_ADDR=:80 可同时启动 HTTP 308 重定向监听。完整字段和安全注意事项见 docs/configuration.md 和 docs/deployment.md。

Docker

正式 Dockerfile 使用 digest 固定的 Go/Alpine builder、精确 libvips 版本和非 root UID 65532。缓存和暂存目录必须挂载为可写卷:

docker build --pull --build-arg VERSION=1.0.0 -t s3imgproxy:1.0.0 .
docker run --rm --read-only --tmpfs /tmp \
  -v s3imgproxy-cache:/var/cache/s3imgproxy \
  -v s3imgproxy-tmp:/var/lib/s3imgproxy/tmp \
  -e S3IMGPROXY_ORIGIN_URL=https://origin.example.com \
  -p 8080:8080 s3imgproxy:1.0.0

本地示例 Compose:

docker compose up --build -d
curl -fsS http://127.0.0.1:8080/healthz

配置

所有环境变量在启动时解析、校验,修改后需要重启。敏感变量包括固定回源头、AWS secret、OAuth secret、mTLS 私钥、Bearer token、签名密钥和 admin token;它们不会写入日志或错误响应。完整类型、默认值、范围和重启要求见 docs/configuration.md。

关键资源限制:

变量 默认值 作用
S3IMGPROXY_MAX_SOURCE_BYTES 32 MiB 单源 body 处理上限
S3IMGPROXY_MAX_OUTPUT_BYTES 64 MiB 生成图片输出上限
S3IMGPROXY_MAX_SPOOL_BYTES 256 MiB 并发暂存总预算
S3IMGPROXY_MAX_PIXELS 100,000,000 解压缩炸弹防护
S3IMGPROXY_MAX_CONCURRENCY 4 libvips 请求并发
S3IMGPROXY_PROCESS_TIMEOUT 15s 单请求处理超时

观测和管理

  • GET /healthz 只表示进程存活。
  • GET /readyz 检查临时目录是否可用。
  • GET /metrics 输出 Prometheus 文本指标;配置 S3IMGPROXY_ADMIN_TOKEN 后需要 Bearer。
  • 配置 admin token 后注册 /debug/decision、POST /admin/cache/purge 和 POST /admin/cache/prewarm。
  • 配置 S3IMGPROXY_ENABLE_PPROF=true 且设置 admin token 后注册受保护 pprof。

日志为 JSON,包含 request ID、源站/暂存/处理耗时、缓存状态、回退原因和错误分类;不会记录 query、Authorization、Cookie 或签名内容。

构建和测试

项目最低 Go 版本为 1.23。按照项目约束,构建和测试统一在 Ubuntu SSH 虚拟机执行:

export PATH="$HOME/.local/go/bin:$PATH"
go test -mod=vendor ./...
go test -mod=vendor -tags libvips ./...
go vet -mod=vendor -tags libvips ./...
go test -mod=vendor -race ./...
go build -mod=vendor -tags libvips ./cmd/s3imgproxy

Parser fuzz、libvips 集成测试、Docker non-root/只读根文件系统验证和性能采样命令见 docs/fault-testing.md、docs/performance.md 和 docs/libvips.md。

设计约束

无处理参数的路径不读取完整响应体;处理路径只在必要时暂存,内存超过阈值切换到私有临时文件。源站连接池复用、libvips 内部单线程、请求级并发 semaphore、singleflight、atomic cache rename 和 fail-open cache 共同控制延迟、内存和高并发下的尾部放大。

许可证

MIT,见 LICENSE。

About

High-performance S3 image reverse proxy, with room for future media support

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages