Кабинет

Свои моки

Свой путь, метод, код и тело ответа с плейсхолдерами — эндпоинты, которых нет ни у одного из сервисов стенда.

На этой странице · 6

Мок-шлюз повторяет Bitrix24, Ozon, Wildberries и Apify. Если разрабатываемому коду нужен эндпоинт, которого нет ни у одного из них, — внутренний ERP, платёжный шлюз, чужой сервис партнёра — его заводят руками в разделе «Свои моки». Такой мок живёт в песочнице, отвечает по ключу песочницы и пишется в тот же журнал запросов.

Адрес и поля мока

Все свои моки обслуживает одна ветка — /custom/*. Путь, начинающийся иначе, сервер не принимает: POST /api/mocks с путём /erp/x отвечает 400 и сообщением «Путь мока начинается с /custom/ — по этому адресу его вызывает песочница».

Поля мока

ПолеЗначенияЧто задаёт
httpMethodGET POST PUT PATCH DELETEметод; HEAD и OPTIONS движок не обслуживает
pathначинается с /custom/, 2–300 символовадрес; сегмент {имя} — параметр пути
title2–120 символовназвание в списке слева
statusdraft active disabledотвечает только active
responseStatusCode200–599код ответа; в редакторе — переключатель 200 / 201 / 400 / 500
contentTypeстрока до 120 символовв редакторе — application/json, application/xml, text/plain
delayMs0–3000задержка перед ответом; ползунок с шагом 10 мс
templatingEnabledда / нетподставлять ли плейсхолдеры
responseBodyдо 200 000 символовтело ответа, шаблон

Пара «метод + путь» уникальна внутри песочницы. Повторное создание возвращает 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/*

КодТелоКогда
код мокатело мокамок найден и активен
401UNAUTHORIZEDключ не передан, неверен или отозван
404MOCK_NOT_FOUNDпо этому методу и пути мока нет
409MOCK_NOT_ACTIVEмок в статусе «черновик» или «выключен»

Параметры пути

Сегмент вида {id} совпадает с любым непустым значением. Сначала ищется точное совпадение пути, потом шаблонное; число сегментов должно совпасть, пустой сегмент параметром не считается. Значение приходит в шаблон уже раскодированным (decodeURIComponent), поэтому /custom/orders/A%2F42 даёт params.id = A/42.

Плейсхолдеры

Плейсхолдеры подставляются в тело ответа при каждом вызове, если включена шаблонизация. Список, который редактор показывает в правой колонке, — тот же, что отдаёт GET /api/mocks в поле placeholders.

Плейсхолдеры

ЗаписьЧто подставляет
{{uuid}}уникальный идентификатор, формат UUID v4
{{now}}текущие дата и время в ISO 8601 без миллисекунд
{{now +3d}}сдвиг даты: +/- и единица d, h, m, s
{{randomInt a b}}случайное целое, границы включаются
{{faker.company}}название компании из восьми заготовленных
{{faker.city}}город из восьми заготовленных
{{request.body.*}}поле из тела запроса, путь через точку
{{params.id}}параметр из пути /custom/orders/{id}

Шаблонизатор понимает ещё {{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. В фильтре «Сервис» на экране логов такого значения нет — эти строки видны только при выбранном «все сервисы».
  • Тело ответа своего мока в журнале не хранится и не восстанавливается: в карточке запроса оно останется пустым. Причины — в разделе Журнал запросов.