Skip to content

refactor: trim Cloudflare API, bundle interceptors + Priority, silo warm-proxy - #116

Merged
cnuss merged 6 commits into
mainfrom
refactor/api-trim-and-warm-proxy-job
Jul 24, 2026
Merged

refactor: trim Cloudflare API, bundle interceptors + Priority, silo warm-proxy#116
cnuss merged 6 commits into
mainfrom
refactor/api-trim-and-warm-proxy-job

Conversation

@cnuss

@cnuss cnuss commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Four related cleanups to the public surface and CI. Pre-v1 (0.x), so the breaking API changes are fine.

1. Remove WithFlushInterval

Drops the method and LIBTUNNEL__CLOUDFLARE_FLUSH_INTERVAL. The reverse proxy still always fronts the origin (stdlib-default flushing); the flush-interval lever — the last vestige of the removed streaming shim — is gone. newOriginProxy loses its flushInterval param.

2. WithApiURLWithProvider(host)

Rename + LIBTUNNEL__CLOUDFLARE_API_URLLIBTUNNEL__CLOUDFLARE_PROVIDER. Takes a bare host (api.trycloudflare.com) and synthesizes https://<host>/tunnel. A value carrying a scheme (http://127.0.0.1:8080/tunnel) is used verbatim — the escape hatch that keeps the mock-endpoint tests working. Default unchanged in effect.

3. WithInterceptor(Interceptor)

Was WithInterceptor(match MatchFn, handler InterceptFn); now takes the existing Interceptor{Match, Handler} struct as one value. Semantics of both fns unchanged. This lets reusable interceptors ship as constructors:

tun.WithInterceptor(addHeader("X-Served-By", "libtunnel"))

README leads with a dead-simple header-adding middleware (wrap ctx.Handler(), set a header, next(w, r)); TestInterceptWrapsDefaultHandler pins that pattern.

Interceptor.Priority

Interceptor gains a Priority int. WithInterceptor keeps the registry sorted by descending Priority (stable — equal-Priority keeps registration order), so the highest-Priority match wins. The zero value = plain registration order, so it stays behavior-compatible until a Priority is set. Lets a specific interceptor override a broad one explicitly (the ALB-rule model), safer than add-order for a live-mutable registry.

4. CI: silo the proxy warmer

warm proxy.golang.org moves out of the release job into its own warm-proxy job (needs: release, reads new release outputs tag/skip). A transient proxy.golang.org 5xx now fails only that job — a one-click isolated rerun — instead of false-failing an already-published release (v0.0.34/v0.0.35 both hit this). continue-on-error/|| true dropped so the failure is visible and rerunnable; curl retries kept.

Build/vet/fmt/tests/-race all green.

🤖 Generated with Claude Code

cnuss and others added 2 commits July 24, 2026 09:24
Four related cleanups to the public surface and CI (0.x, breaking is fine).

1. Remove WithFlushInterval + LIBTUNNEL__CLOUDFLARE_FLUSH_INTERVAL. The
   reverse proxy still fronts the origin with the stdlib default; the flush
   lever is gone (it was the last vestige of the removed streaming shim).

2. Rename WithApiURL -> WithProvider(host) and LIBTUNNEL__CLOUDFLARE_API_URL
   -> LIBTUNNEL__CLOUDFLARE_PROVIDER. Takes a bare host (api.trycloudflare.com)
   and synthesizes https://<host>/tunnel; a value carrying a scheme is used
   verbatim (escape hatch for a mock/alternate endpoint).

3. WithInterceptor(Interceptor) instead of (MatchFn, InterceptFn). The pair is
   already the Interceptor struct; taking it as one value lets reusable
   interceptors ship as constructors: tun.WithInterceptor(addHeader(...)).
   README leads with a plain header-adding middleware example (wrap
   ctx.Handler()); added TestInterceptWrapsDefaultHandler.

4. CI: move "warm proxy.golang.org" out of the release job into its own
   warm-proxy job (needs: release, reads release outputs tag/skip). A
   transient proxy.golang.org 5xx now fails only that job — a one-click
   isolated rerun — instead of false-failing an already-published release.
   Release exports tag/skip as job outputs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a Priority int to Interceptor. WithInterceptor keeps the registry sorted
by descending Priority (stable, so equal-Priority interceptors keep
registration order), and Intercept's first-match scan therefore yields the
highest-Priority match. The zero value leaves everything equal, i.e. plain
registration order — so this is behavior-compatible with the prior
first-registered-wins semantics until a Priority is set.

Lets a specific interceptor override a broad one explicitly, without depending
on the order it was added (the ALB-listener-rule model), which is safer than
add-order for a live-mutable registry.

Docs (v1 struct/registry godoc, README) + TestInterceptPriorityWins.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cnuss cnuss changed the title refactor: trim Cloudflare API, bundle interceptors, silo warm-proxy refactor: trim Cloudflare API, bundle interceptors + Priority, silo warm-proxy Jul 24, 2026
cnuss and others added 4 commits July 24, 2026 09:39
Add Priority int to Interceptor. Registration keeps the registry sorted by
descending Priority (stable → equal Priorities keep registration order), so
Intercept's first-match scan yields the highest-Priority match.

A Priority of 0 is auto-assigned an increasing value via an atomic counter
(10, 20, …), so among unprioritized interceptors the later-registered one
wins. An explicit non-zero Priority raises that lane to its value — monotonic,
never lowering it, so a low fallback Priority can't drag the lane down — and
the next default then lands one step above it.

Docs (v1 struct/registry godoc, README) + tests: later-default-wins,
explicit-high-wins, explicit-low-is-fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…cessor

Reorient Interceptor.Priority to AWS-ALB semantics and expose the registry.

- Priority is now uint16; the LOWEST wins (0 = highest precedence). The
  registry is kept sorted ascending, ties in registration order.
- A Priority of 0 (unset) is auto-assigned from math.MaxUint16 downward
  (atomic counter, saturating at 0), so unprioritized interceptors sit at the
  low-precedence end: a later-registered one wins over an earlier one, and any
  explicit Priority outranks them all. Explicit priorities no longer nudge the
  auto counter.
- Add Tunnel.Interceptors() returning a snapshot in precedence order (auto
  Priorities resolved) for visibility into the effective ordering.

Docs (v1 struct/registry/Tunnel godoc, README) + tests: later-default-wins,
lower-Priority-wins, explicit-beats-default, and the accessor ordering.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0 is the zero value that triggers auto-assignment, not a usable precedence, so 1
is the highest settable Priority (65535 the lowest). Spell that out in the
Interceptor.Priority / Interceptors godoc and the README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cnuss
cnuss merged commit 0223420 into main Jul 24, 2026
18 checks passed
@cnuss
cnuss deleted the refactor/api-trim-and-warm-proxy-job branch July 24, 2026 14:07
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