Кабинет
Свои моки
Свой путь, метод, код и тело ответа с плейсхолдерами — эндпоинты, которых нет ни у одного из сервисов стенда.
На этой странице · 6
Мок-шлюз повторяет Bitrix24, Ozon, Wildberries и Apify. Если разрабатываемому коду нужен эндпоинт, которого нет ни у одного из них, — внутренний ERP, платёжный шлюз, чужой сервис партнёра — его заводят руками в разделе «Свои моки». Такой мок живёт в песочнице, отвечает по ключу песочницы и пишется в тот же журнал запросов.
Адрес и поля мока
Все свои моки обслуживает одна ветка — /custom/*. Путь, начинающийся иначе,
сервер не принимает: POST /api/mocks с путём /erp/x отвечает 400
и сообщением «Путь мока начинается с /custom/ — по этому адресу его вызывает песочница».
Поля мока
Пара «метод + путь» уникальна внутри песочницы. Повторное создание возвращает 409:
{"error":"ALREADY_EXISTS","message":"Мок POST /custom/erp/orders/{id} уже создан"}
Коды ниже 200 отклоняются на схеме: 1xx — не ответ, а промежуточный сигнал,
клиент продолжил бы ждать тело и повис до таймаута.
Вызов мока
Мок вызывается тем же ключом песочницы, что и остальные эндпоинты стенда.
curl -X POST 'localhost:8080/custom/erp/orders/A-42' \
-H "X-Mock-Key: $KEY" \
-H 'content-type: application/json' \
-d '{"items":[{"sku":"2037841009335"}]}'
Ответ несёт x-request-id и x-apistend-source: custom-mock — по второму заголовку
свой мок отличается от ответа мок-шлюза, где источником стоит example, schema
или generic.
Ответы ветки /custom/*
Параметры пути
Сегмент вида {id} совпадает с любым непустым значением. Сначала ищется точное
совпадение пути, потом шаблонное; число сегментов должно совпасть, пустой сегмент
параметром не считается. Значение приходит в шаблон уже раскодированным
(decodeURIComponent), поэтому /custom/orders/A%2F42 даёт params.id = A/42.
Плейсхолдеры
Плейсхолдеры подставляются в тело ответа при каждом вызове, если включена
шаблонизация. Список, который редактор показывает в правой колонке, — тот же,
что отдаёт GET /api/mocks в поле placeholders.
Плейсхолдеры
Шаблонизатор понимает ещё {{query.имя}} — значение параметра строки запроса.
В панели редактора его нет, но в ответе он работает.
Тело ответа с восемью подстановками и живой ответ на запрос выше:
{
"id": "{{params.id}}",
"uuid": "{{uuid}}",
"createdAt": "{{now}}",
"dueAt": "{{now +3d}}",
"amount": {{randomInt 1000 9000}},
"company": "{{faker.company}}",
"city": "{{faker.city}}",
"sku": "{{request.body.items.0.sku}}",
"typo": "{{unknown}}"
}
{
"id": "A-42",
"uuid": "efe8d1d2-c7f1-4223-8d52-ca8918fdf3b1",
"createdAt": "2026-09-09T10:15:04Z",
"dueAt": "2026-09-12T10:15:04Z",
"amount": 3472,
"company": "ООО «Первая мебельная»",
"city": "Санкт-Петербург",
"sku": "2037841009335",
"typo": "{{unknown}}"
}
Три правила подстановки, которые видно в этом ответе:
- Путь в
request.bodyидёт по вложенности и по индексам массива:items.0.sku. Отсутствующее поле даёт пустую строку, а неnullи не ошибку. - Незнакомый плейсхолдер остаётся в тексте как есть —
{{unknown}}. Так опечатка видна в предпросмотре, а не превращается в тихо пропавшее поле. {{now}}отдаёт время с точностью до секунды. Неподъёмный сдвиг вроде{{now +999999999d}}выходит за допустимый диапазон дат и остаётся текстом.
Предпросмотр и тест-вызов
Предпросмотр под редактором (POST /api/mocks/preview) подставляет плейсхолдеры
в текущий текст шаблона, не сохраняя мок. Он детерминированный: источник случайности
солится идентификатором песочницы и самим шаблоном, поэтому один и тот же текст
даёт один и тот же вид при каждом открытии, а не «плывёт» на каждом нажатии клавиши.
Образец тела запроса зашит в предпросмотр:
{"externalId": "EXT-10422", "customer": {"id": "C-77"}, "items": [{"sku": "2037841009335"}]}
Кнопка «Тест-вызов» (POST /api/mocks/:id/test) вызывает сохранённый мок по сессии
кабинета, а не по ключу: полный ключ показывается один раз при создании и кабинет
его не хранит. Отличия от настоящего вызова два:
- задержка не выдерживается, значение
delayMsпросто возвращается в ответе; - параметрам пути, которых не передали, подставляется
sample-<имя>.
В ответе есть servedPublicly — признак того, что мок в статусе active и по
публичному адресу тоже ответит. Черновик в тест-вызове отвечает, а на /custom/* — нет.
Подводные камни
Правил ответа и своих заголовков пока нет
В редакторе нарисованы вкладки «Правила ответа», «Заголовки», «Задержка и ошибки»
и «История вызовов», но переключение не меняет содержимое: правил в продукте нет,
поле rules у мока всегда пустое, а мета-строка «N правил» всегда показывает ноль.
Свои заголовки ответа тоже не отдаются — ответ несёт только Content-Type мока
и служебные заголовки песочницы. Всё, что мок умеет, настраивается в правой колонке.
Content-Typeв ответе приезжает с добавленной кодировкой:application/jsonпревращается вapplication/json; charset=utf-8.- Задержка входит в время запроса в журнале: мок с
delayMs: 250даёт в логе около 260 мс. - Запросы к своим мокам пишутся в журнал с сервисом
custom. В фильтре «Сервис» на экране логов такого значения нет — эти строки видны только при выбранном «все сервисы». - Тело ответа своего мока в журнале не хранится и не восстанавливается: в карточке запроса оно останется пустым. Причины — в разделе Журнал запросов.