proxy

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 30, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package proxy provides NewReverseProxy — the one-liner that turns a session-affine process pool into an HTTP gateway.

Why this exists

Pool.Acquire gives you a *Session. But in the common case — proxying HTTP traffic to a subprocess — you still need to write the reverse-proxy loop yourself: acquire a session, build a *httputil.ReverseProxy pointing at session.Worker.Address(), forward the request, handle errors. That's 30 lines every user copy-pastes. NewReverseProxy collapses it to one call.

Usage

pool, _ := herd.New(&herd.FirecrackerFactory{...})

proxy := proxy.NewReverseProxy(pool, func(r *http.Request) string {
    return r.Header.Get("X-Session-ID")
})

http.ListenAndServe(":8080", proxy)

Session lifecycle

NewReverseProxy acquires a session at the START of each HTTP request and releases it at the END (after the response is written). This means a single HTTP request holds a worker exclusively for its duration — appropriate for request-scoped work (a browser API call, an LLM inference call, a REPL eval).

For long-lived sessions where the same sessionID should stay pinned across many requests — e.g. a stateful REPL session that must keep the same process — callers should call Pool.Acquire / Session.Release directly and store the *Session in their own state (e.g. an HTTP session cookie → in-memory map).

Error handling

If extractSessionID returns an empty string, ServeHTTP returns 400. If Pool.Acquire fails (timeout, all workers crashed), ServeHTTP returns 503. If the upstream subprocess returns a non-2xx, it is forwarded as-is — the proxy does not interfere with application-level error codes.

File layout

proxy/proxy.go   — NewReverseProxy + ReverseProxy.ServeHTTP (THIS FILE)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ReverseProxy

type ReverseProxy[C any] struct {
	LookupOnly bool // If true, only routing to existing sessions; won't Acquire/Scale
	// contains filtered or unexported fields
}

ReverseProxy is an http.Handler that acquires a session from pool, proxies the request to the worker's address, and releases the session when done.

C is the worker client type — for FirecrackerFactory this is *http.Client. ReverseProxy does not use C directly; it proxies via the worker's Address().

func NewReverseProxy

func NewReverseProxy[C any](
	pool *herd.Pool[C],
	extractSessionID func(*http.Request) string,
) *ReverseProxy[C]

NewReverseProxy returns an http.Handler that:

  1. Calls extractSessionID(r) to determine which session this request belongs to.
  2. Calls pool.Acquire(ctx, sessionID) to get (or create) the pinned worker.
  3. Reverse-proxies the request to worker.Address().
  4. Calls session.Release() after the response is written.

extractSessionID may inspect any part of the request — a header, a cookie, a path prefix, or a query parameter. It must return a non-empty string.

Example: route by X-Session-ID header:

proxy := proxy.NewReverseProxy(pool, func(r *http.Request) string {
    return r.Header.Get("X-Session-ID")
})

func (*ReverseProxy[C]) ServeHTTP

func (rp *ReverseProxy[C]) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

Steps:

  1. Extract sessionID — return 400 if empty.
  2. Acquire/Lookup session — return 404/503 if unavailable.
  3. Parse worker address into *url.URL.
  4. Build a per-request httputil.ReverseProxy targeting that URL.
  5. Forward request; on response write, release the session.

func (*ReverseProxy[C]) WithLifecycleManager added in v0.5.0

func (rp *ReverseProxy[C]) WithLifecycleManager(lm *lifecycle.Manager) *ReverseProxy[C]

WithLifecycleManager injects a lifecycle manager into the proxy.

func (*ReverseProxy[C]) WithLookupOnly

func (rp *ReverseProxy[C]) WithLookupOnly() *ReverseProxy[C]

WithLookupOnly configures the proxy to only route to existing sessions. It will not trigger worker allocation or singleflight slow paths. Useful for stateless Data Plane proxies (Daemon Mode).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL