Skip to content

fix: mirror header forwarding, auth, cache accounting, and CI build speed - #8

Merged
wha7ev9r merged 2 commits into
mainfrom
fix/bugs-and-docker-build
Jul 31, 2026
Merged

fix: mirror header forwarding, auth, cache accounting, and CI build speed#8
wha7ev9r merged 2 commits into
mainfrom
fix/bugs-and-docker-build

Conversation

@wha7ev9r

Copy link
Copy Markdown
Owner

背景

围绕三个问题:docker pull 镜像代理不可用、dashboard 部分功能失效、CI 双平台构建耗时 ~8min。

高优先级修复(P0)

  • 镜像代理不转发客户端请求头ProxyHTTP/ProxyStream 现在转发 Authorization/Range/Accept 等头(原只透传 path/query),docker pull(含私有镜像)、HuggingFace Range 断点续传从此可用
  • /v2/ registry 401 无限递归:加深度限制(>2 次即返回 401),私有仓库/scope 错误不再死循环
  • io.ReadAll 全量缓冲 OOM 风险:可缓存响应改为流式写入临时文件 + 原子 rename;且只缓存 200(206 部分内容绝不入缓存)
  • 限流 IP 可伪造X-Real-IP/X-Forwarded-For 仅在连接方为回环地址(本机反代)时信任;顺手修复 IPv6 RemoteAddr 解析与 IPv6 CIDR 默认前缀
  • /api/search 未鉴权 + 无超时:补鉴权,统一走 10s 超时专用 client
  • gitproxy raw/blob 404:raw.githubusercontent.com 路径多出的 /raw/ 段已移除(新增路径断言测试)
  • 15 个镜像配置热加载失效ProxyHandler 改为每次请求读取 upstream/TTL(与 npm/docker 一致)

中优先级修复(P1)

  • gitproxy.enabled 配置项真正生效(为 false 时不注册 /gh/ /gl/ 路由)
  • 缓存 usedBytes 记账:启动扫描磁盘初始化、删除/淘汰时扣减(max_size 限定额失效问题)
  • 登录接口恒定时间比较 + 参与限流(不再豁免 /api/
  • /api/config/public 补鉴权
  • 前端:Search 翻页失效(has_more 字段)、per_page 参数失效、Settings rate 保存必 400、401 跳转登录、client/router 循环依赖、已登录可访问 /login、无 404 路由
  • vite dev 代理补全全部镜像前缀(原缺失 13 个)
  • compose/README 镜像引用统一为 ghcr.io/wha7ev9r/devbox(原指向 ksbbs 旧仓库,导致拉不到新版本)
  • 清理死文件(icons.svg/vue.svg/vite.svg/hero.png/package-lock.json)、favicon 加版本号

Docker 构建优化

多阶段构建重构:前端仅构建一次(--platform=$BUILDPLATFORM,静态产物无架构差异),Go 交叉编译(CGO_ENABLED=0 + $TARGETARCH,免 QEMU),runtime 按目标平台拉基础镜像,另加 BuildKit cache mount(pnpm store / GOMODCACHE / GOCACHE)。预计双平台构建 8min → 3-4min,需 CI 实测确认。

验证

  • go build ./... / go vet ./... / go test ./... 全部通过(新增 ratelimit、gitproxy 测试)
  • pnpm run build(vue-tsc + vite)通过

wha7ev9r added 2 commits July 31, 2026 15:13
…peed

P0 fixes:
- ProxyHTTP/ProxyStream now forward client headers (Authorization, Range,
  Accept) so docker pull, HuggingFace range requests and private registry
  pulls work through the mirrors
- Cap /v2/ registry 401 retry recursion (was unbounded loop on private repos)
- Stream cacheable responses to disk instead of buffering with io.ReadAll
  (avoids OOM on large wheels/tarballs); cache 200 only, never 206
- Rate limiter ignores forged X-Real-IP/X-Forwarded-For unless peer is
  loopback; fix IPv6 RemoteAddr parsing and IPv6 CIDR defaults
- /api/search now requires auth and uses a 10s-timeout client
- gitproxy raw/blob URLs no longer carry the extra /raw/ segment (was 404)
- 15 mirror handlers read upstream/TTL per request so runtime config
  changes (hot reload / dashboard edits) take effect

P1 fixes:
- gitproxy.enabled now actually gates /gh/ and /gl/ routes
- Cache usedBytes accounting: scan on startup, decrement on eviction
- Constant-time login comparison + login endpoint rate limited
- /api/config/public requires auth
- Frontend: search pagination (has_more), per_page param, Settings rate
  save, 401 redirect, router/client circular import, login redirect,
  catch-all 404 route, full vite dev proxy list
- Align compose/README image refs to ghcr.io/wha7ev9r/devbox
- Remove dead assets (icons.svg, vue.svg, vite.svg, hero.png,
  package-lock.json), bump favicon cache version

CI:
- Dockerfile: build frontend once on BUILDPLATFORM, cross-compile Go for
  TARGETARCH (no QEMU emulation), BuildKit cache mounts
  (expected multi-arch build time ~8min -> ~3-4min)
…ew favicon

Review fixes:
- ProxyHTTP spools to a unique temp file per request (os.CreateTemp) so
  concurrent misses on the same key can no longer interleave writes and
  corrupt cache entries; ScanSize/evictLRU skip .tmp-* files
- Authenticated requests (Authorization header) bypass shared cache
  read/write entirely — URL-only keys would otherwise leak one client's
  authenticated responses to everyone (e.g. /ghapi/ with a PAT)
- Strip hop-by-hop headers (Connection, Transfer-Encoding, Upgrade,
  Proxy-Authorization, ...) when forwarding to upstreams, in both
  mirror.Cache and gitproxy
- Rate limiter trusts X-Real-IP / X-Forwarded-For only from peers within
  configurable rate_limit.trusted_proxies CIDRs (loopback by default),
  fixing the Docker + host-nginx deployment where peers appear as the
  bridge gateway; New() falls back to loopback defaults when unset

Icon:
- New favicon: isometric purple gradient box with cyan terminal prompt
  (>_), radial dark panel, glass highlight, soft shadow (v3 cache bump)
- Header logo upgraded from text badge to inline SVG cube + wordmark
@wha7ev9r
wha7ev9r merged commit 3debfd8 into main Jul 31, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant