Session Recipes & Go Collector Export
Capture bootstrap-once/per-request session economics and export a standalone Go client.
A session recipe records how an API session is economical: which call mints the session tuple once, how long that tuple stays valid, and which fields must be recomputed on every send. Once the recipe matches observed traffic, Traffic Jam transpiles it — together with the decode codec, derivation functions, and mTLS wiring — into a standalone Go collector you can build and run outside the workspace. Both features live in the API lab under the Collector tab → Recipes view.
Session economics: bootstrap once, derive per request
A recipe is an ordered list of steps, each tagged with a role:
| Role | When it runs | Purpose |
|---|---|---|
bootstrap | Once per session, while its extracts are stale | Mints the session tuple (e.g. an /event call that returns session cookies/CSRF values). Its extracts are cached and reused. |
per-request | On every recipe run | The actual workload call; derived fields (signed cookies, timestamps, nonces) are recomputed per send. |
Bootstrap freshness is bounded by two knobs, both optional (0 = unlimited):
- max age (seconds) — bootstrap re-runs when the last run is older than this.
- max uses — bootstrap re-runs after this many recipe runs have consumed the tuple.
While the tuple is fresh, bootstrap steps are skipped (the run report shows skipped (fresh)) and only the per-request steps fire. A failed bootstrap invalidates the session and stops the run immediately.
Build a recipe from observed traffic
Recipes are edited on a full-screen, Blueprints-style node graph. Open the API lab, switch to the Collector tab, open the Recipes view, and click New recipe (or edit an existing one). The graph opens as an immersive canvas with a toolbar, the node graph, and a details panel:
- In the toolbar, enter a Name and the bootstrap freshness bounds (defaults:
600seconds,25uses). - Add nodes with the toolbar buttons or by right-clicking the canvas: Bootstrap, Per-request, and Derivation. New step nodes are wired onto the end of the execution chain automatically.
- Select a node to edit it in the details panel: pick the captured request, declare bootstrap extracts, set request overrides, or fill in a derivation’s target and template. Pan by dragging the background, zoom with the wheel, and drag nodes to arrange them.
- Wire the run order by dragging from a node’s white execution pin to the next node — the chain starting at the session recipe’s
Runpin is the order the collector executes (bootstrap steps first, then per-request steps). - Declare bootstrap extracts in the details panel as
name+source+expression. Supported sources arejson(dotted path, leading$.optional),header,cookie(fromSet-Cookie), andregex(first capture group, or the whole match). Each extract appears as a colored output pin, and the graph auto-routes a data wire to every derivation or per-request step that references that variable by name. - Click Store recipe. The recipe is saved to the project database (with a
localStoragemirror undertraffic-jam:session-recipesas an offline cache); run state (last bootstrap time, use count, cached extracts) is kept inlocalStorageundertraffic-jam:recipe-runtimes.
Dry-run validates extracts and derivations against the captured responses without sending live traffic.
Run a recipe
Click Run on a recipe. The runner walks the steps in order, replaying each captured request through the normal replay path (so replay safety rules still apply). Extracted bootstrap values are merged into the variable set that per-request sends see — the same {{name}} mechanism described in /docs/en/replay/variables/.
The Last run report shows a badge per step: the HTTP status, skipped (fresh) for a cached bootstrap, or error with the message. A step whose captured request is no longer loaded reports step request is not loaded.
[!WARNING] Recipe runs replay real requests with captured credentials included and auto-confirm state-changing methods. Only run recipes against systems you are authorized to test.
Export a standalone Go collector
Click Export Go on a recipe. The generator lifts endpoints, ordered headers, and cookies from each step’s captured request, transpiles your derivation templates to Go, and downloads a single main.go.
Derivations are declared in the Derivations for collector export box, one per line, as target = template (split on the first =). The template uses the same computed-field DSL as replay:
cookie:fgssca-goldapple = p = randomHex:4; p + sha1(fgsscSecret + cookie:gssca-goldapple + p) | skip:4
The transpiler supports these constructs:
| DSL | Generated Go |
|---|---|
sha1(x), md5(x), sha256(x) | tjSha1Hex / tjMd5Hex / tjSha256Hex |
hmac-sha1(key, x), hmac-sha256(key, x) | tjHmacSha1 / tjHmacSha256 |
base64(x), crc32(x) (bare → body) | tjBase64 / tjCrc32 |
nowMs(), nowSec(), uuid4(), randomHex:n | tjNowMs / tjNowSec / tjUUID / tjRandomHex |
cookie:n, header:n, query:n, var:n, body | lookups in the cookie/header/query/var maps |
pipes | skip:n (trunc), | take:n (prefix), | upper, | lower, | urlencode, | base64 | tjSkip / tjTake / strings.To* / tjURLEncode / tjBase64 |
name = expr; … statements | local variables, so a nonce can match in two places |
What the generated code contains
- A
DO NOT EDIT by hand — regenerate from the session recipe insteadheader, plus a comment stating the bootstrap max-age/max-uses economics. sessionState(StartedAt,Uses,Vars) with afresh()method encoding the freshness bounds.doRequest, a helper that sets ordered headers, serializes the cookie jar in sorted name order, and caps response reads at 4 MiB.- One
step_<id>function per recipe step: captured headers and cookies, JSON extracts via adigStringpath walker, header extracts viaresponseHeaders.Get. - One
derive_<target>function per derivation, called inrun()before the per-request sends. - The
tj*helper set, and the Group-IB packet codec (manglePacket/unmanglePacket, position-dependent char shift plus a CRC32 wrapper). - mTLS wiring:
tls.LoadX509KeyPair, anhttp.Clientwith a 30 s timeout,ForceAttemptHTTP2, andMinVersion: tls.VersionTLS12.
Build and run the collector
The export downloads main.go (package main). Build it as a normal Go module:
mkdir productcard && cd productcard
go mod init productcard
mv ../Downloads/main.go .
go build ./...
Run it, pointing at the client certificate (a combined cert+key PEM):
CLIENT_CERT=client.pem ./productcard
# or
./productcard -cert client.pem
The -cert flag defaults to $CLIENT_CERT, falling back to client.pem. See /docs/en/replay/fingerprints/ for how the workspace manages client certificates and /docs/en/collector/conformance/ for checking the collector’s fingerprint against the reference capture.
Export behavior and limitations
| Area | Behavior |
|---|---|
regex extracts | Wired to a regexExtract helper that returns the first capture group, or the whole match when the pattern has no groups. |
| Derivation targets | cookie:name, header:name, query:name, json:path, and body targets are all injected into the request automatically. |
| Untranspilable template | The export refuses and returns an error naming the target instead of emitting a hand-written TODO placeholder — fix the template and re-export. |
| UI export toggles | The Recipes panel always emits mTLS wiring and the Group-IB codec. |
| Bootstrap body | With the codec enabled, a bootstrap step without an explicit body sends manglePacket(vars["packet"]). |
| Storage | Recipes sync to the project database; run state (last bootstrap time, use count, cached extracts) lives only in the browser’s localStorage and is not shared. |
[!NOTE] The generated collector is a starting point for an authorized, rate-limited client against a system you own or are permitted to test — review the emitted headers, bodies, and certificate handling before running it.