Руководство

Подмена ответа API на реальном устройстве

Ответьте на один из API-вызовов вашего приложения заготовленным ответом — на телефоне у вас в руке, без поддельного сервера и без пересборки. Правило блокировки Mock для фиксированного тела, лимит запусков, когда оно должно сработать ровно один раз, и скрипт, когда тело нужно вычислить.

Подмена на реальном устройстве — то место, где рассыпается большинство схем: заглушка живёт на ноутбуке, телефон должен до неё дотянуться, а приложение — на неё указывать. Busymate DevTools помещает подмену прямо в путь перехвата. Правило блокировки следит за каждым запросом, совпадающим с методом и шаблоном хост-плюс-путь, и само отвечает на совпадение — синтетической ошибкой, обрывом соединения или подменным успехом, который выглядит в точности как ответ от источника. Upstream-сервер никогда не вызывается.

Правила применяются в двух местах, так что покрыт каждый режим подключения: прокси-сервер для браузеров, Android через прокси и iOS в режиме PAC, а также VPN-туннель на устройстве для iOS в режиме VPN. Глобальные правила действуют на всех устройствах; правила для устройства накладываются сверху. Изменения расходятся по Realtime, поэтому сохранённое правило работает на телефоне без переподключения.

Перед началом

Что вам понадобится

Телефон, который уже перехватывает, и эндпоинт, который вы хотите подменить.

  • Спаренный телефон с включённым перехватом — сначала пройдите руководство для iPhone или Android.

  • Хост API в списке SSL proxy этого устройства. Правило, сопоставляющее путь, видит путь только у расшифрованного хоста.

  • Метод, хост и путь вызова, на который вы хотите ответить, и тело, которое ожидает ваше приложение.

  • Только для варианта со скриптом: возможность «скрипты» админского уровня в вашей роли. Обычным правилам Mock особая роль не нужна.

Шаг за шагом

Делайте по порядку

Шаги с первого по четвёртый дают фиксированную подмену. Пятый и шестой закрывают два случая, которые фиксированное тело не покрывает: сработать один раз и вычислить ответ.

  1. 01

    Убедитесь, что хост расшифрован

    Откройте ленту дашборда и найдите реальный запрос к эндпоинту. Если в его строке видно расшифрованное тело — вы готовы. Если хост всё ещё показан зашифрованным, добавьте его в список SSL proxy устройства — через действия с хостом в строке или в настройках устройства — и вызовите запрос снова. У хоста, проходящего зашифрованным, движок может сопоставить только имя хоста; путь невидим, поэтому точная по пути подмена никогда не сработает.

  2. 02

    Откройте Blocks и добавьте правило

    Откройте страницу Blocks из навигации настроек для глобального правила или перейдите к устройству, затем в Blocks — для правила только для этого телефона. Добавьте правило и укажите метод — или оставьте пустым, чтобы совпадал любой — и шаблон. Шаблоны — те же маски хост-плюс-путь, что и у точек останова: хост, косая черта, путь, со звёздочкой там, где сегмент меняется.

  3. 03

    Выберите Mock и сформируйте ответ

    Установите действие Mock. Если Block нужен, чтобы вызов провалился, а Drop делает вид, что сеть пропала, то Mock призван его удовлетворить: задайте статус — по умолчанию 200, — заголовки, на которые смотрит приложение, и тело. Укажите тот Content-Type, который разбирает ваше приложение; JSON-клиент, получивший текстовый ответ, упадёт, не прочитав ни байта. В виде JSON правило выглядит так.

    Правило Mock, отвечающее на вызов feature flags фиксированным телом
    json
    {
      "enabled": true,
      "method": "GET",
      "pattern": "api.example.com/v1/feature-flags",
      "action": {
        "type": "mock",
        "status": 200,
        "headers": { "Content-Type": "application/json" },
        "body": "{\"flags\": {\"newCheckout\": true}}"
      }
    }
  4. 04

    Сохраните, вызовите запрос и проверьте ленту

    Сохраните правило и воспользуйтесь приложением. Следующий совпавший запрос получает ответ, не покидая путь перехвата, и всё равно появляется в вашей ленте — с пометкой о подмене, так что вы точно видите, что было подделано, и убеждаетесь, что правило сделало ожидаемое. Приложение видит лишь обычный ответ сервера: синтетические ответы не несут внутренних или опознавательных заголовков, так что ничто в ответе не выдаёт перехват.

    Когда закончите, выключите правило его переключателем. Отключённое правило ничего не стоит и сохраняет форму до следующего раза.

  5. 05

    Сработать ровно один раз с лимитом запусков

    Некоторые подмены должны случаться один раз. Классика — синтетический 401, заставляющий приложение поверить, что токен истёк, и запустить обновление; ответьте так на каждый запрос — и приложение обновит токен, повторит, снова получит 401 и закрутится навечно. Поле Max runs ограничивает, сколько раз правило может сработать; по достижении лимита оно отключает себя, и редактор показывает бейдж автоотключения, отличный от правила, выключенного вами вручную.

    Счётчик ведётся для каждого устройства и переживает переподключения и перезапуски приложения, так что лимит в единицу срабатывает один раз вообще на этом телефоне, а не раз за сессию. Глобальное правило с лимитом подавляется только на устройстве, которое его исчерпало, и продолжает срабатывать на всех остальных телефонах парка. Можно также попросить BusyBro обычным языком об одноразовой подмене 401 для хоста — он напишет то же правило.

    Одноразовый 401 — обычная подмена плюс лимит в единицу
    json
    {
      "enabled": true,
      "method": "GET",
      "pattern": "api.example.com/v1/me",
      "action": {
        "type": "mock",
        "status": 401,
        "headers": { "Content-Type": "application/json" },
        "body": "{\"error\": \"token_expired\"}"
      },
      "maxRuns": 1
    }
  6. 06

    Вычислите тело скриптом

    Тело Mock — одна замороженная строка. Когда ответ должен зависеть от запроса — возвращённый id, метка времени, поле, вписанное в реальный ответ, — переключите действие правила на Script или создайте отдельный скрипт в Settings, затем Scripts. Вы получаете редактор кода с автодополнением для объектов запроса, ответа и помощников и панель Test, которая прогоняет скрипт на реальной перехваченной записи и показывает diff «до и после», не трогая живой трафик. Сухой прогон использует ту же песочницу, что и живой прокси, так что пройденный тест означает, что скрипт работает вживую.

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

    Хук запроса, который замыкает его вычисленным JSON-телом
    javascript
    function onRequest(req) {
      if (req.path.startsWith("/v1/feature-flags")) {
        // computed per request — the upstream is never contacted
        return Response.json({ flags: { newCheckout: true, seed: Date.now() } }, { status: 200 });
      }
      // no return → forward unchanged
    }

Устранение неполадок

Что может пойти не так

Правило, которое кажется мёртвым, почти всегда сопоставляет то, чего не видит.

  • Правило никогда не срабатывает

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

  • Приложение застряло в цикле обновления токена

    Ваш синтетический 401 срабатывает на каждый запрос. Установите Max runs в единицу, чтобы правило отключилось после первого срабатывания, а повторный запрос дошёл до реального сервера.

  • Приложение отвергает подменный ответ

    Обычно не хватает заголовка Content-Type или форма тела не совпадает с тем, что разбирает клиент. Скопируйте заголовки и тело реального перехваченного ответа из инспектора как отправную точку.

  • У правила бейдж автоотключения

    Оно исчерпало лимит запусков на этом устройстве. Очистите Max runs или включите правило заново, чтобы снова его взвести.

  • Скрипт выполнился, но ответ пришёл настоящий

    Скрипт бросил исключение или превысил таймаут и отказал в открытую. Откройте запись в инспекторе — бейдж ошибки содержит сообщение и строку, — исправьте в редакторе и снова прогоните панель Test на той же записи, прежде чем включать.

ЧаВО

Частые вопросы

Может ли приложение понять, что ответ подменён?

Не по самому ответу. Подменный 200 или заблокированный 403 не несёт опознавательных заголовков и выглядит как обычный ответ источника. Видимость односторонняя: помеченная запись появляется только в вашей ленте.

Работает ли это на iOS в режиме VPN или только через прокси?

И так и так. Один и тот же движок правил работает внутри VPN-туннеля iOS и на прокси-сервере, поэтому iOS в любом режиме, Android через прокси и браузеры одинаково соблюдают правило.

Нужно ли что-то передеплоить, когда я меняю правило?

Нет. Правила живут в тех же настройках, которые расходятся на устройства по Realtime, поэтому сохранение сразу применяется к новым соединениям. Уже открытое keep-alive-соединение сохраняет конфигурацию, с которой началось, до переподключения.

Подделайте ответ, оставьте телефон настоящим

Одно правило в дашборде — и приложение у вас в руке получает ответ, который вы хотите проверить, без заглушки и без пересборки.

Ask your mate