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:

RoleWhen it runsPurpose
bootstrapOnce per session, while its extracts are staleMints the session tuple (e.g. an /event call that returns session cookies/CSRF values). Its extracts are cached and reused.
per-requestOn every recipe runThe 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:

  1. In the toolbar, enter a Name and the bootstrap freshness bounds (defaults: 600 seconds, 25 uses).
  2. 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.
  3. 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.
  4. 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 Run pin is the order the collector executes (bootstrap steps first, then per-request steps).
  5. Declare bootstrap extracts in the details panel as name + source + expression. Supported sources are json (dotted path, leading $. optional), header, cookie (from Set-Cookie), and regex (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.
  6. Click Store recipe. The recipe is saved to the project database (with a localStorage mirror under traffic-jam:session-recipes as an offline cache); run state (last bootstrap time, use count, cached extracts) is kept in localStorage under traffic-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:

DSLGenerated 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:ntjNowMs / tjNowSec / tjUUID / tjRandomHex
cookie:n, header:n, query:n, var:n, bodylookups in the cookie/header/query/var maps
pipes | skip:n (trunc), | take:n (prefix), | upper, | lower, | urlencode, | base64tjSkip / tjTake / strings.To* / tjURLEncode / tjBase64
name = expr; … statementslocal 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 instead header, plus a comment stating the bootstrap max-age/max-uses economics.
  • sessionState (StartedAt, Uses, Vars) with a fresh() 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 a digString path walker, header extracts via responseHeaders.Get.
  • One derive_<target> function per derivation, called in run() 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, an http.Client with a 30 s timeout, ForceAttemptHTTP2, and MinVersion: 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

AreaBehavior
regex extractsWired to a regexExtract helper that returns the first capture group, or the whole match when the pattern has no groups.
Derivation targetscookie:name, header:name, query:name, json:path, and body targets are all injected into the request automatically.
Untranspilable templateThe 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 togglesThe Recipes panel always emits mTLS wiring and the Group-IB codec.
Bootstrap bodyWith the codec enabled, a bootstrap step without an explicit body sends manglePacket(vars["packet"]).
StorageRecipes 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.

Traffic Jam documentation. Built with Hugo.