# echolot send (/ru/docs/cli/send)

`echolot send` отправляет один запрос и пишет тело ответа в стандартный вывод. Передайте ему URL, как передали бы curl,
или путь к сохранённому запросу в рабочем пространстве, и он отправит его так, как это делает приложение: с
переменными, авторизацией, скриптами и проверками. Он также открывает сеансы WebSocket и Socket.IO и слушает потоки
событий.

```sh
echolot send [<options>] <url>
```

`<url>` — это URL или путь к сохранённому файлу запроса (`.req.toml`, `.gql.toml` или `.mcp.toml`) в папке
`requests` рабочего пространства.

## Отправка URL [#send-a-url]

```sh
echolot send https://demo.echolot.dev/v1/products/TNT-MH-2P
```

Тело идёт в стандартный вывод, поэтому его можно передать дальше (`| jq .`) или записать в файл с `-o`. Больше ничего
не печатается, пока вы не попросите:

- `-i` печатает строку статуса и заголовки перед телом.
- `-v` печатает время в стандартный поток ошибок: DNS, подключение, TLS, ожидание и передачу, размер и хеш тела, удалённый
  адрес, версию TLS, выбранный протокол и сертификаты сервера. У декодированного тела (gzip, Brotli, zstd) показан размер
  до и после.
- `--wire` печатает в стандартный поток ошибок точные байты, отправленные и полученные, как они пойманы в сети.

Тело и заголовки:

```sh
echolot send https://demo.echolot.dev/echo/anything -X POST \
  -H 'Content-Type: application/json' \
  -d '{"sku": "TNT-MH-2P"}' -v
```

```text
── body ── decoded zstd 257 → 418 bytes
── timing ──
DNS          79.61 ms
Connect      15.65 ms
TLS          28.70 ms
Waiting      19.75 ms
Transfer      0.53 ms
Total       146.36 ms
Body      418 bytes, sha256 01facf0b2388ca67…
Remote    [2606:4700:3031::6815:3cf1]:443
── tls ── TLS 1.3, ALPN h2
CN=echolot.dev
  issuer CN=WE1,O=Google Trust Services,C=US, valid until 30 Jan 2027
Alt-Svc   the server offers HTTP/3 (h3 on port 443); --http3 uses it, and so do later requests on Automatic in the same run
```

`-H` сохраняет порядок и регистр ваших заголовков. `--data-file` передаёт тело из файла потоком, а не читает его в
память, так что подходит для больших загрузок. `--raw` не отправляет заголовков, которые вы не написали: ни `Host`, ни
`Content-Length`, ни `Accept-Encoding`.

## Отправка сохранённого запроса [#send-a-saved-request]

Передайте путь к файлу запроса. Echolot находит рабочее пространство вокруг него, разрешает `{{variables}}` с выбранным
вами окружением, выполняет скрипты и проверки запроса и печатает результаты:

```sh
echolot send Alpenglow.echolot/requests/catalog/get-product.req.toml -i
```

```text
HTTP/2 200 OK
content-type: application/json; charset=utf-8
etag: W/"TNT-MH-2P-1"
…

{
  "sku": "TNT-MH-2P",
  "name": "Matterhorn 2P Tent",
  …
}
── tests ──
✓ Status equals 200
✓ JSON value $.sku equals {{productId}}
2 passed
```

- `-e staging` или `--env staging` разрешает запрос с окружением из `environments/staging.toml`.
- Секретные переменные берутся из переменных `ECHOLOT_SECRET_<NAME>` или, на Mac, из Связки ключей. См.
  [секреты](/docs/cli#secrets).
- То, что скрипты выводят в журнал, появляется под `── console ──`, а результаты проверок и `pm.test` — под
  `── tests ──`, в стандартном потоке ошибок. Непройденная проверка даёт код выхода 1.
- Переменная, которая не разрешилась, печатается как предупреждение до отправки запроса.
- `-X`, `-H`, `-d` и `--data-file` предназначены для URL; сохранённый запрос отправляет то, что написано в его файле.
  `--timeout`, `--http1.1`, `--http2`, `--http3`, `--raw`, `-k`, `--listen`, параметры прокси и сертификата действуют
  для обоих случаев.

## Потоки событий, WebSocket и Socket.IO [#event-streams-websocket-and-socketio]

**Server-Sent Events.** Ответ с `text/event-stream` идёт в стандартный вывод по мере поступления. `--listen`
задаёт, как долго слушать: по умолчанию 10 секунд, `0` — пока сервер не завершит поток.

```sh
echolot send https://demo.echolot.dev/v1/orders/events --listen 0
```

**WebSocket.** URL `ws://` или `wss://` открывает сеанс. Каждая введённая (или переданная по конвейеру) строка и `-d`
отправляются как текстовое сообщение; приходящие сообщения печатаются по одному в строке, двоичные — в Base64. Когда
ввод заканчивается, Echolot слушает ещё `--listen` секунд и закрывает сеанс. `--subprotocol` предлагает подпротокол и
может быть указан несколько раз. `-i` или `-v` печатает ответ на обновление протокола в стандартный поток ошибок.

```sh
echo '{"op": "subscribe", "channel": "orders"}' | echolot send wss://demo.echolot.dev/v1/orders --listen 5
```

**Socket.IO.** `--socketio` говорит на Socket.IO через URL `http(s)://` или `ws(s)://`. Каждая входная строка — это
событие: его имя, затем аргументы в JSON (`chat {"text": "hi"}`; массив — это несколько аргументов). События печатаются
как `name [arguments]`, подтверждения — как `ack id [arguments]`.

```sh
echolot send http://localhost:3001 --socketio --namespace /support --auth '{"token": "demo"}'
```

Серверы, на которых можно это попробовать, см. в [запросах Socket.IO](/docs/requests/socket-io).

## Параметры [#options]

| Параметр | Значение |
| --- | --- |
| `-e`, `--env <env>` | Окружение, с которым разрешается сохранённый запрос: имя его файла без `.toml`. |
| `-X`, `--request <method>` | Метод HTTP; допустим любой токен. По умолчанию `GET`. |
| `-H`, `--header <header>` | Заголовок в виде `'Name: value'`. Можно повторять; порядок и регистр сохраняются. |
| `-d`, `--data <data>` | Тело запроса, заданное прямо в команде. |
| `--data-file <file>` | Передавать тело запроса из этого файла потоком. |
| `-o`, `--output <file>` | Записать тело в этот файл вместо стандартного вывода. |
| `--raw` | Сырой режим: не отправлять никаких автоматических заголовков. |
| `-k`, `--insecure` | Пропустить проверку сертификата TLS. |
| `-i`, `--include` | Напечатать строку статуса и заголовки перед телом. |
| `-v`, `--verbose` | Напечатать разбивку времени в стандартный поток ошибок. |
| `--wire` | Напечатать точные отправленные и полученные байты в стандартный поток ошибок. |
| `--listen <seconds>` | Сколько секунд слушать поток событий, прежде чем завершить; `0` — пока его не завершит сервер. По умолчанию 10. |
| `--timeout <seconds>` | Тайм-аут всего обмена. По умолчанию 60. |
| `--http1.1` | Отправлять только по HTTP/1.1. |
| `--http2` | Отправлять только по HTTP/2: ALPN поверх TLS, prior knowledge поверх обычного HTTP. |
| `--http3` | Отправлять только по HTTP/3, поверх QUIC: только `https://`, без прокси; macOS 27 и новее, а также Linux. |
| `--subprotocol <name>` | Для URL `ws://` и `wss://`: подпротокол, который предлагается. Можно повторять. |
| `--socketio` | Говорить на Socket.IO; каждая входная строка — `event [JSON arguments]`. |
| `--namespace <namespace>` | Для `--socketio`: пространство имён, к которому присоединиться. По умолчанию — путь URL, иначе `/`. |
| `--auth <json>` | Для `--socketio`: данные авторизации, объект JSON. |
| `--socketio-version <version>` | Для `--socketio`: версия Socket.IO на сервере, `4` (также для 3) или `2`. По умолчанию 4. |
| `--socketio-path <path>` | Для `--socketio`: где слушает сервер. По умолчанию `/socket.io/`. |
| `--proxy <url>` | Отправлять через этот прокси: `http://host:port`, `https://…`, `socks5://user:password@host:port`. |
| `--no-proxy` | Подключаться напрямую, игнорируя `HTTP_PROXY` и остальные. |
| `--cacert <file>` | Дополнительно доверять сертификатам ЦС из этого файла PEM. Можно повторять. |
| `--cert <file>` | Отправлять этот клиентский сертификат: файл PEM (вместе с `--key`) или файл `.p12`/`.pfx`. |
| `--key <file>` | Закрытый ключ клиентского сертификата в PEM, когда в файле сертификата его нет. |
| `--pass <passphrase>` | Парольная фраза ключа или файла PKCS#12. Лучше использовать переменную окружения `ECHOLOT_CERT_PASSPHRASE`. |

Без `--http1.1`, `--http2` и `--http3` Echolot выбирает версию так, как это делает параметр **Автоматически** в
приложении. Выберите только один из них.

## Коды выхода [#exit-codes]

| Код | Когда |
| --- | --- |
| `0` | Ответ ниже 400, и все проверки прошли. |
| `1` | Нет ответа (причина печатается), либо проверка или тест не прошли. |
| `22` | Статус ответа 400 или выше. Тело всё равно записывается. |
| `64` | Неверный параметр, URL, который URL не является, или файл вне рабочего пространства. |

Скрипт перед запросом, который вызывает `pm.execution.skipRequest()`, ничего не отправляет и завершается с кодом 0.
