# Toxiproxy-compatible API

> Point Toxiproxy clients and test suites at Cloak Proxy. Its Toxiproxy-compatible HTTP API creates proxies and toxics (latency, bandwidth, timeout, reset_peer, slicer, limit_data, slow_close) that become failure scenarios, and every request through them shows in the traffic list.

Source: https://docs.subcloak.com/cloak-proxy/automation/toxiproxy/

Added in Cloak Proxy 0.4.0.

(added in Cloak Proxy 0.4.0)

[Toxiproxy](https://github.com/Shopify/toxiproxy) is a common way for test suites to break the network on purpose: add latency, cut bandwidth, time out or reset connections. Cloak Proxy can serve the same HTTP API, so a suite that already drives Toxiproxy can point at Cloak Proxy instead, and you see every request it breaks in the traffic list, with what was done to it.

Each Toxiproxy **proxy** becomes a listener that forwards to its upstream through Cloak Proxy. Each proxy's **toxics** become the faults of a [failure scenario](https://docs.subcloak.com/cloak-proxy/tools/failure-scenarios/) named **Toxiproxy: *name***, so you can watch their counts and log in the Failure Scenarios window.

## Turn it on

1. In **Tools › Failure Scenarios…**, switch on **Toxiproxy API** under the scenario list. Or run `cloakctl toxiproxy on` (add `--api-port N` for a port other than 8474), or ask an assistant to use the `toxiproxy_api` MCP tool.

2. Point your Toxiproxy client at `http://127.0.0.1:8474`, the address Toxiproxy uses by default.

3. Create proxies and toxics as your suite already does. Requests to a proxy's `listen` address go to its `upstream` through Cloak Proxy.

```sh
cloakctl toxiproxy on
curl -s -X POST localhost:8474/proxies -d '{"name":"api","listen":"127.0.0.1:26380","upstream":"127.0.0.1:8080"}'
curl -s -X POST localhost:8474/proxies/api/toxics -d '{"type":"latency","attributes":{"latency":1000}}'
curl -s http://127.0.0.1:26380/health        # arrives a second late, and shows in Cloak Proxy
cloakctl toxiproxy off
```

The API listens on 127.0.0.1 only, and refuses requests that come from web pages (with an `Origin` header). Like Toxiproxy's, it has no token. It's off until you turn it on.

## Endpoints

| Request | What it does |
|---|---|
| `GET /version` | The version (`2.9.0-cloakproxy`). |
| `GET /proxies` | Every proxy, by name. |
| `POST /proxies` | Create a proxy: `name`, `upstream` (`host:port`), `listen` (default `127.0.0.1:0`, which picks a free port), `enabled`. `409` if the name or port is taken. |
| `POST /populate` | Create several proxies (an array), replacing ones with the same names. |
| `GET`, `POST`, `DELETE /proxies/{name}` | Read, change (`enabled`, `listen`, `upstream`) or delete a proxy. |
| `GET`, `POST /proxies/{name}/toxics` | List the proxy's toxics, or add one: `type`, `name` (default `type_stream`), `stream`, `toxicity` (0–1), `attributes`. |
| `GET`, `POST`, `DELETE /proxies/{name}/toxics/{toxic}` | Read, change (`toxicity`, `attributes`) or remove a toxic. |
| `POST /reset` | Enable every proxy and remove every toxic. |

Errors come back as Toxiproxy's do: `{"error": "proxy not found", "status": 404}`.

## How toxics act

Toxiproxy works on raw TCP bytes. Cloak Proxy forwards HTTP and HTTPS, so each toxic acts on whole requests:

| Toxic | In Cloak Proxy |
|---|---|
| `latency` (`latency`, `jitter`) | Delays each request by the latency plus half the jitter. |
| `bandwidth` (`rate`, KB/s) | Sends responses at that rate. |
| `slicer` (`average_size`, `delay` µs) | Sends responses at `average_size` bytes per `delay`. |
| `timeout` (`timeout` ms) | No answer; the connection closes after the timeout (`0`: after an hour). |
| `reset_peer` | Resets the connection. |
| `limit_data` (`bytes`) | Sends that many bytes of the body, then closes the connection. |
| `slow_close` (`delay` ms) | Delays the request by that long. |
| `toxicity` below 1 | Applies to that share of requests, at random. |
| A disabled proxy | Resets every connection. |

`stream` (`upstream` or `downstream`) is accepted and kept, but every toxic acts on the request and its response as a whole.

## Limits

- Upstreams must be HTTP or HTTPS. An upstream on port 443, or written as an `https://` URL, is HTTPS; anything else is HTTP. Databases and other TCP protocols aren't forwarded.
- A proxy's faults match its upstream's host and port, so they also apply to requests that reach that upstream through Cloak Proxy's main port.
- Deleting a proxy closes its listener; connections already open finish their current request.
- Proxies, toxics and whether the API is on are saved with your rules.

## Related

  - [Failure scenarios](https://docs.subcloak.com/cloak-proxy/tools/failure-scenarios/): Break requests on a schedule, with a log.
  - [cloakctl](https://docs.subcloak.com/cloak-proxy/automation/cloakctl/): The command-line tool.
  - [Headless and CI](https://docs.subcloak.com/cloak-proxy/automation/headless-and-ci/): Run tests through Cloak Proxy.
