---
title: "Run Echo Upstream"
url: "https://docs.caracal.run/examples/echo-upstream/"
markdown_url: "https://docs.caracal.run/markdown/examples/echo-upstream.md"
description: "Start the local protected target that proves Gateway-brokered requests reach an upstream service."
page_type: "workflow"
concepts: []
requires: []
---

# Run Echo Upstream

Canonical URL: https://docs.caracal.run/examples/echo-upstream/
Markdown URL: https://docs.caracal.run/markdown/examples/echo-upstream.md
Description: Start the local protected target that proves Gateway-brokered requests reach an upstream service.
Page type: workflow
Concepts: none
Requires: none

---

Echo Upstream is a zero-dependency HTTP service under `examples/echoUpstream`. It stands in for the API you would put behind Caracal, so you can verify a Gateway-mediated request end to end without hosting your own upstream. Every response states whether the call was brokered by the Gateway or hit the service directly, and shows the evidence behind that verdict.

## What it demonstrates

| Area | Behavior |
| --- | --- |
| Brokered-call proof | Reports `viaGateway` plus the request ID, trace context, and forwarding metadata the Gateway stamped on the request. |
| Credential handling | Confirms the Gateway injected the brokered credential and redacts credential values from the echoed headers. |
| Gateway reachability | Joins the `caracalData` Docker network so Gateway can reach `http://echoUpstream:8088`. |
| Local debugging | Exposes `http://127.0.0.1:8088` on the host and logs one line per request, marked `[gateway]` or `[direct]`. |

## Run with Docker

```bash
cd examples/echoUpstream
docker compose -f compose.yml up --build
```

Check the local health endpoint:

```bash
curl http://127.0.0.1:8088/healthz
```

## Run with Node

```bash
cd examples/echoUpstream
npm start
```

The server listens on port `8088`. Set `ECHO_PORT` when you need a different local port.

## Use as the protected upstream

In Console guided setup or through the Control API, create a resource with this upstream URL:

```text
http://echoUpstream:8088
```

Then send a request to the Gateway with the Caracal access token and resource ID from guided setup. The Console result view prints the exact command for your setup; it has this shape:

```bash
curl http://localhost:8081/v1/hello \
  -H "Authorization: Bearer $CARACAL_RESOURCE_PIPERNET_TOKEN" \
  -H "X-Caracal-Resource: resource://pipernet"
```

## Read the response

A brokered call returns `"viaGateway": true` with a `gateway` section:

| Field | What it proves |
| --- | --- |
| `viaGateway` | The request carried the Gateway's request ID and forwarding metadata. |
| `gateway.requestId` | Audit handle — paste it into Console **explain** to trace the policy decision. |
| `gateway.credentialInjected` | The Gateway brokered a credential the client never held. |
| `request.headers` | The headers the upstream actually received, with credentials redacted. |

Calling `http://127.0.0.1:8088/` directly returns `"viaGateway": false`, which makes the difference between a protected and an unprotected path visible.

## Test

```bash
cd examples/echoUpstream
npm test
```

## Next step

Continue to [Bootstrap Control State](/examples/control-bootstrap/) when you want repeatable setup for demo resources and policies.
