# Динамические значения (/ru/docs/requests/dynamic-values)

Динамическое значение — это токен, который Echolot вычисляет при каждой отправке запроса: текущее время, новый UUID,
подпись тела или значение из последнего ответа другого запроса. Пишется оно как переменная, только с `$` впереди:
`{{$uuid}}`, `{{$sha256('{{password}}')}}`. Динамические значения работают везде, где работают переменные: в URL,
параметрах, заголовках, теле, полях форм и полях авторизации.

На этой странице показано, как их добавлять и редактировать. Все динамические значения с аргументами перечислены в
[справочнике динамических значений](/docs/reference/dynamic-values).

## Добавление из списка [#add-one-from-the-list]

1. В любом поле, которое принимает переменные, введите `{{`. Откроется список: сначала переменные из текущей области,
   затем динамические значения по категориям.
2. Продолжайте вводить, чтобы сузить список: `uuid`, `time`, `hmac`. Каждая запись говорит, что она даёт.
3. Перемещайтесь клавишами <kbd>↑</kbd> и <kbd>↓</kbd>, а <kbd>↩</kbd> или <kbd>⇥</kbd> вставляют значение;
   <kbd>Esc</kbd> закрывает список.

Значение с аргументами сразу после вставки открывает свой редактор, так что аргументы вы заполняете в форме, а не
набираете. Чтобы открыть список, не вводя `{{`, щёлкните поле правой кнопкой и
выберите **Вставить переменную или значение…**.

В поле динамическое значение выглядит как «таблетка» с понятной подписью: название значения (`HMAC-SHA256`) или, для
значения из ответа, запрос и то, что читается (`Sign in › $.access_token`). Текст под ней остаётся как написан.

<Shot id="requests-http-token-editor" alt="Редактор токена для значения «JSONPath Filtered Response»: запрос Sign in, JSONPath $.access_token, «Сначала отправить» со значением «Если ответа ещё нет» и значение из последнего ответа" />

## Редактирование токена [#edit-a-token]

Дважды щёлкните «таблетку» или щёлкните её правой кнопкой и выберите **Изменить токен…**. Откроется редактор токена:

- Кнопка вверху показывает, чем является токен, и позволяет это изменить: переменной или динамическим значением.
- Поля — это аргументы значения. Аргумент-запрос — это меню запросов рабочего пространства по папкам; у аргумента-запроса
  к ответу (JSONPath, XPath, имя заголовка) есть кнопка со списком того, что содержит последний ответ, так что значение
  можно выбрать, а не вводить путь.
- **Значение** показывает, что токен даёт сейчас, с текущим окружением, или **Не разрешается в текущем окружении** с
  причиной.
- Для переменной **Использовать другую переменную** заменяет её другой, а **Использовать значение из ответа** превращает
  её в значение из ответа.
- **Удалить** удаляет токен; **Готово** сохраняет изменения.

## Быстрый просмотр [#quick-look]

Наведите указатель на «таблетку», чтобы увидеть, что она даёт, не открывая её: значение (для секрета оно скрыто и
помечено **Секрет**), откуда оно берётся и как записано. Для динамических значений быстрый просмотр сообщает, когда они
вычисляются: время и случайные значения — **Создаётся заново при каждой отправке; выше — пример.** Кнопки: **Изменить…**,
**Скопировать значение** и **Все переменные…**, которая открывает панель переменных.

## Запись вручную [#writing-them-by-hand]

```text
{{$name}}                       no arguments
{{$name('text', 42)}}           text in single or double quotes, numbers as they are
{{$base64(user)}}               a bare name is a variable
{{$base64('{{user}}:{{pass}}')}} variables inside text
{{$sha256("{{$requestBody('')}}")}} a dynamic value inside another one
```

Токен внутри аргумента в кавычках должен использовать для собственных аргументов кавычки другого вида: двойные вокруг
токена, аргументы которого стоят в одинарных, как в последней строке.

## Что можно использовать [#what-you-can-use]

| Категория | Примеры | Что даёт |
| --- | --- | --- |
| **Ответы** | `{{$response('auth/sign-in', '$.access_token')}}`, `{{$responseHeader('orders/create-order', 'Location')}}`, `{{$responseStatus('auth/sign-in')}}` | Значения из последнего ответа другого запроса. |
| **Запросы** | `{{$requestHeader('', 'Content-Type')}}`, `{{$requestURL('auth/sign-in')}}`, `{{$requestJSONPath('', '$.lines[0].sku')}}` | Части этого запроса (пустой первый аргумент) или другого — в том виде, в каком они были бы отправлены. |
| **Кодирование** | `{{$base64('heidi:alpenglow')}}`, `{{$urlEncode('a b&c')}}`, `{{$jsonEscape('say "hi"')}}`, `{{$basicAuth('heidi', '{{password}}')}}`, `{{$jwt('{"sub": "heidi"}', '{{jwtSecret}}')}}`, `{{$newline}}` | Закодированный или декодированный текст, экранирование, значение Basic-авторизации, подписанный JWT. |
| **Хеши и подписи** | `{{$sha256("{{$requestBody('')}}")}}`, `{{$hmacSha256('{{key}}', 'message', 'base64')}}`, `{{$md5('text')}}` | Хеши и HMAC в hex, если не запрошен `base64` или `base64url`. |
| **Время** | `{{$timestamp}}`, `{{$timestampMs}}`, `{{$isoTimestamp}}`, `{{$httpDate}}`, `{{$date('yyyy-MM-dd', -86400, 'Europe/Zurich')}}` | Время отправки в секундах или миллисекундах Unix, в ISO 8601, как дата HTTP или в вашем формате, со смещением в секундах и в заданном часовом поясе. |
| **Случайные** | `{{$uuid}}`, `{{$randomInt(1, 6)}}`, `{{$randomString(16)}}`, `{{$randomHex(8)}}` | Новые случайные значения при каждой отправке. `$guid` и `$randomUUID` — другие имена `$uuid`. |
| **Тестовые данные** | `{{$randomFullName}}`, `{{$randomEmail}}`, `{{$randomCity}}`, `{{$randomPrice}}`, `{{$randomLoremSentence}}`, `{{$randomDatePast}}` | Выдуманные имена, адреса, компании, цены, даты, lorem ipsum и многое другое, новые при каждой отправке, под именами из Postman. В списке они сгруппированы по подменю. См. [тестовые данные](/docs/reference/dynamic-values#fake-data). |
| **Текст** | `{{$lowercase('{{name}}')}}`, `{{$uppercase('chf')}}`, `{{$trim('{{code}}')}}` | Изменённый текст. |
| **Файлы и система** | `{{$file('data/order.json')}}`, `{{$env('HOME')}}` | Содержимое файла (путь относительно рабочего пространства или абсолютный) либо переменная окружения процесса Echolot. |

`$env` недоступно агентам: когда запрос отправляет ИИ-агент, переменные окружения вашего Mac остаются вне его досягаемости.

Пример Alpenglow использует одно из них в **Orders › Create order**: заголовок `Idempotency-Key` равен `{{$uuid}}`,
поэтому каждый заказ новый.

## Значения из ответов других запросов [#values-from-other-requests-responses]

Значения из категории **Ответы** читают последний ответ другого сохранённого запроса. Первый аргумент — путь этого
запроса в рабочем пространстве: его папка и его имя, как в файлах: `auth/sign-in` для **Auth › Sign in**.

| Значение | Что читает |
| --- | --- |
| `$response(request, query)` | Что угодно, по виду запроса: `$.token` (JSONPath), `/feed/entry[1]/id` (XPath), `header:Location`, `cookie:session`, `regex:token=(\w+)`, `jq:.data.token`, `keypath:data.items.0.id`. |
| `$responseJSONPath`, `$responseKeyPath`, `$responseJq`, `$responseXPath`, `$responseRegex` | Тело — запросом такого вида. Regex даёт свою первую группу, если она есть. |
| `$responseHeader`, `$responseCookie` | Заголовок или cookie, установленный ответом. |
| `$responseStatus`, `$responseBody`, `$responseBodyLength` | Код состояния, тело как текст, его размер в байтах. |

Если у запроса, который читает значение, ещё нет ответа, Echolot сначала отправляет его. Строка под адресной строкой
сообщает об этом до отправки: **Сначала отправляет «Sign in»**. Необязательный последний аргумент решает, когда это
происходит; в редакторе токена он называется **Сначала отправить**:

| Аргумент | В редакторе | Что происходит |
| --- | --- | --- |
| (нет) или `'if-missing'` | **Если ответа ещё нет** | Отправляет другой запрос, только если у него нет ответа. |
| `'fresh'` | **Каждый раз** | Отправляет его перед каждой отправкой этого запроса (в Прогоне — один раз за прогон). |
| `'latest'` | **Никогда: брать последний ответ** | Никогда его не отправляет; берёт его последний ответ. |

```text
{{$response('auth/sign-in', '$.access_token', 'fresh')}}
```

Запросы, которые читают друг друга по кругу, отклоняются с указанием этих запросов.

Чтобы сохранить значение из ответа в переменной, которую читают все запросы, а не ссылаться на один запрос,
используйте [захват из ответа](/docs/requests/captures).

## Значения из этого запроса [#values-from-this-request]

Значения из категории **Запросы** читают запрос в том виде, в каком он был бы отправлен, с подставленными переменными и
авторизацией. Оставьте первый аргумент пустым для отправляемого запроса: `{{$requestHeader('', 'X-Request-Id')}}`.
Echolot вычисляет только ту часть, о которой вы просите, так что заголовок может подписывать тело:

```text
X-Signature: {{$hmacSha256('{{signingKey}}', "{{$requestBody('')}}")}}
```

## jq [#jq]

Фильтры jq работают в `$responseJq`, `$requestJq` и `$response(…, 'jq:…')`, ничего устанавливать не нужно. Фильтр с
несколькими результатами выдаёт их по одному на строку:

```text
{{$responseJq('catalog/list-products', '.items[0].sku')}}
{{$responseJq('catalog/list-products', '[.items[].price.amount] | add')}}
```

## Если значение не разрешается [#when-a-value-doesnt-resolve]

Токен, который нельзя вычислить (нет переменной, у запроса нет ответа и его нельзя отправить, JSONPath ничего не
находит), отправляется как написан, а строка под адресной строкой показывает **1 проблема**. Нажмите её, чтобы
увидеть, какая именно. То же говорят редактор токена и быстрый просмотр.
