Referencie valores entre blocos
A sintaxe {{...}} é o que transforma o httui de “um editor
markdown” em “um runtime encadeado”. Esse guia é o cheatsheet
completo de referências: de onde vêm, pra onde podem ir, que
regras de escopo se aplicam.
Anatomia de uma referência
Seção intitulada “Anatomia de uma referência”{{ alias . campo . path }} ^^^^^ ^^^^^ ^^^^ | | | | | JSON path dentro do campo | body | status | headers | cookies | row alias do bloco cuja response você querEspaço em branco dentro de {{ ... }} é permitido mas
desencorajado pra grep-ability.
Campos disponíveis em toda response de bloco
Seção intitulada “Campos disponíveis em toda response de bloco”| Campo | O que é | Exemplo |
|---|---|---|
body | Body da response JSON-parseado (ou texto se não for JSON) | {{login.body.token}} |
status | Status code HTTP numérico | {{login.status}} |
headers.<name> | Valor de header de response | {{login.headers.x-request-id}} |
cookies.<name> | Valor de set-cookie | {{login.cookies.session}} |
size | Tamanho do body em bytes | {{download.size}} |
time | Tempo total em ms | {{slow.time}} |
Blocos DB têm um campo extra:
| Campo | O que é | Exemplo |
|---|---|---|
row[N] | n-ésima linha do result set | {{users_list.row[0].email}} |
rows | Array completo de linhas | {{users_list.rows}} (raro) |
affected | Linhas afetadas por INSERT/UPDATE/DELETE | {{seed.affected}} |
JSON paths
Seção intitulada “JSON paths”Depois de body. você pode navegar em qualquer formato JSON com
notação ponto e indexação [N]:
```http alias=orderGET {{BASE_URL}}/orders/{{previous.body.data.items[0].id}}Authorization: Bearer {{login.body.tokens.access_token}}```| Pattern | Lê |
|---|---|
body.user.id | { user: { id: 42 } } → 42 |
body.items[0].name | { items: [{ name: "x" }] } → "x" |
body.tags[2] | { tags: ["a", "b", "c"] } → "c" |
body.nested["odd key"] | bracket-quoted pra keys que não são identifier |
body[*].name | NÃO suportado — use blocos encadeados ou expects |
Atalho posicional: {{$prev}}
Seção intitulada “Atalho posicional: {{$prev}}”Quando você não liga pro nome, $prev é “o bloco anteriormente
executado, response como raiz implícita”:
```http alias=loginPOST {{BASE_URL}}/auth/login```
```httpGET {{BASE_URL}}/users/{{$prev.body.user.id}}```{{$prev.body.user.id}} é exatamente {{login.body.user.id}}.
Use quando o alias é óbvio pelo contexto (estilo script de uma só
execução).
Onde referências podem ir
Seção intitulada “Onde referências podem ir”Referências resolvem nessas posições antes do bloco despachar:
| Tipo de bloco | Posição | Exemplo |
|---|---|---|
| HTTP | URL | GET {{BASE_URL}}/x |
| HTTP | key de header | {{HEADER_NAME}}: value |
| HTTP | value de header | Authorization: Bearer {{token}} |
| HTTP | body (qualquer content type) | { "id": {{user.body.id}} } |
| HTTP | query string | ?since={{cutoff.body.iso}} |
| DB | texto SQL | SELECT * FROM x WHERE id = {{user.body.id}} |
| DB | params da conexão (host/port via session override) | {{PG_HOST}} |
| Standalone | body do bloco | depende do tipo de bloco |
Referências não resolvem em tokens da info-string
(alias=..., timeout=...) — esses são configuração, não dados.
Refs SQL são sempre bound
Seção intitulada “Refs SQL são sempre bound”Quando um {{...}} aparece num bloco SQL, o httui não faz
string-interpolation. A referência vira um bind parameter
($1 pra Postgres, ? pra SQLite/MySQL), e o valor resolvido
passa pelo prepared-statement binding do driver:
```db-localSELECT * FROM ordersWHERE customer_id = {{user.body.id}} AND created_at > {{cutoff.body.iso}}```O que o driver vê:
SELECT * FROM ordersWHERE customer_id = $1 AND created_at > $2Valores de bind: [user.body.id, cutoff.body.iso].
Zero superfície de SQL injection, mesmo com valores controlados pelo usuário vindo via responses HTTP.
Prioridade: bloco > env var
Seção intitulada “Prioridade: bloco > env var”Se você tem um bloco com alias BASE_URL e uma env var também
chamada BASE_URL, o bloco vence quando os dois estão em
escopo:
```http alias=BASE_URLGET https://dynamic-discovery.example.com/url```
```httpGET {{BASE_URL}}/health # usa o body da response do bloco como URL!```Isso é by design (dá aos runbooks uma forma de sobrescrever valores de env em runtime), mas é fácil se surpreender. Regra de ouro: use ALL_CAPS pra env vars, snake_case ou kebab-case pra aliases de bloco.
Auto-execução: a DAG
Seção intitulada “Auto-execução: a DAG”Quando você roda um bloco que referencia {{other.body.X}}, o
httui:
- Faz parse das referências no seu bloco.
- Acha que
otheré um alias definido acima do bloco atual. - Checa o cache — se o hash dos inputs de
other(body, env, refs) bate com a run cacheada, usa a response cacheada. - Senão roda
other(que pode disparar dependências upstream — recurse). - Substitui o valor resolvido no seu bloco.
- Roda seu bloco.
Referências só podem apontar pra cima no arquivo. Isso faz do runbook uma DAG por construção — sem ciclos possíveis, sem loops “bloco 3 referencia bloco 7 que referencia bloco 2”.
Quando o valor tá faltando
Seção intitulada “Quando o valor tá faltando”| Causa | O que você vê |
|---|---|
| Alias não existe em nenhum bloco acima | Editor sublinha a ref em vermelho; hover mostra “unknown alias” |
| Path do field não existe na response | Bloco roda, painel mostra erro: “path body.user.id not found in response” |
| Bloco upstream ainda não rodou | O httui roda primeiro (auto-exec) |
| Bloco upstream deu erro | O erro propaga — bloco downstream não roda, painel mostra “upstream login failed” |
Inspecionando valores resolvidos
Seção intitulada “Inspecionando valores resolvidos”| Onde | Como |
|---|---|
| No editor | Hover no {{...}} — popup mostra valor resolvido ou erro |
| Antes da run | O popup atualiza ao vivo conforme o cache enche |
| Depois da run | Aba Raw do painel de response mostra a request literal, todas as refs já substituídas |
| No drawer | Clique no ⚙ da toolbar do bloco → aba References lista cada ref com o valor atual |
Relacionado
Seção intitulada “Relacionado”- Monte um teste de API encadeado — veja referências em ação com um fluxo completo login → me → assert.
- Use variáveis de ambiente —
{{KEY}}sem pontos (sem.body, sem.status— só lookup de string flat). - Faça assert do formato da response —
usando refs dentro de
# expect:pra comparar entre blocos.