Как подменить ответ API без изменения бэкенда
Четыре способа отдать приложению свой JSON: Local Overrides в Chrome, MSW, перехватчик в клиенте и прокси. И когда какой.
Зачем это нужно
Нужно посмотреть, как приложение поведёт себя на ответе, которого бэкенд не даёт: пустой список, 500, двести позиций вместо трёх, поле, которого ещё нет. Трогать бэкенд нельзя: он чужой, или на нём сейчас работают, или это прод. Способов четыре. Разница в том, где стоит подмена: от этого зависит, какой трафик способ достаёт.
Chrome DevTools: Local Overrides
Самый быстрый способ для веба. Ставить ничего не надо.
- DevTools → Network → правый клик по запросу → Override content.
- Выберите папку на диске и дайте к ней доступ.
- Ответ откроется в редакторе. Правьте и сохраняйте через
Ctrl/Cmd+S. - Перезагрузите страницу. Теперь запрос отдаётся из вашего файла.
Ограничений два. Подменить можно тело и заголовки ответа, но не код статуса: 200 в 500 так не превратить. И работает это только в вашем браузере и только при открытых DevTools: закроете их, и вернётся настоящий ответ.
MSW: подмена в самом приложении
msw регистрирует на странице Service Worker. Приложение ходит в сеть как
обычно, а отвечает ему ваш код.
Сначала положите файл воркера в публичную папку:
npx msw init ./public --save
// mocks/handlers.js
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('/api/orders', () =>
HttpResponse.json({ items: [] }), // пустой список
),
http.post('/api/orders', () =>
new HttpResponse(null, { status: 500 }), // ошибка сервера
),
];
// mocks/browser.js
import { setupWorker } from 'msw/browser';
import { handlers } from './handlers';
export const worker = setupWorker(...handlers);
// main.jsx — только в разработке
if (import.meta.env.DEV) {
const { worker } = await import('./mocks/browser');
await worker.start();
}
// приложение рендерим после этого
Дождитесь start() до рендера приложения. Запросы, ушедшие раньше, попадут на
настоящий бэкенд.
Лучший вариант, когда подмена нужна повторяемо: это код, он лежит в
репозитории, работает у всей команды, а в тестах те же обработчики подключаются
через setupServer из msw/node. Минус в том, что способ ограничен своим
веб-приложением: чужое не перехватите, трафик нативного клиента тоже.
Перехватчик в мобильном клиенте
Если исходники ваши, подменяйте там, где работает сеть.
// Android, OkHttp
val mockInterceptor = Interceptor { chain ->
val request = chain.request()
if (BuildConfig.DEBUG && request.url.encodedPath == "/api/orders") {
Response.Builder()
.request(request)
.protocol(Protocol.HTTP_1_1)
.code(500)
.message("Mocked")
.body("""{"error":"boom"}""".toResponseBody("application/json".toMediaType()))
.build()
} else {
chain.proceed(request)
}
}
val client = OkHttpClient.Builder()
.addInterceptor(mockInterceptor)
.build()
Проверку BuildConfig.DEBUG не убирайте. Без неё подмена уедет в релиз, к
пользователям.
Цена способа: нужны исходники, и каждая правка требует пересборки.
Прокси: подмена снаружи приложения
Отладочный прокси подменяет ответ в сети, а не внутри приложения. Поэтому ему всё равно, чьё это приложение и на чём написано: веб-страница, нативный клиент на телефоне, CLI-утилита, чужая программа без исходников. Правило простое: на такой-то адрес отдать такой-то ответ, то есть статус, заголовки и тело, при желании с задержкой. Запрос, который попал под правило, в сеть вообще не уходит.
Это единственный из четырёх способов, который работает, когда:
- приложение не ваше и пересобрать его нельзя;
- трафик идёт с телефона, а не из браузера;
- надо показать коллеге или тестировщику, не заставляя его разворачивать окружение.
Ограничение одно, и важное. Приложение с пиннингом сертификата не примет сертификат прокси: соединение не установится, и в этом трафике вы ничего не увидите и ничего не подмените.
Что выбрать
| Нужно | Чем |
|---|---|
| Посмотреть один раз в своём браузере | Local Overrides |
| Сценарий для всей команды и для тестов | MSW |
| Подмена внутри своего мобильного клиента | перехватчик в коде |
| Чужое приложение или телефон, без пересборки | прокси |
Как увидеть это у себя
В Solpuga правило Map Local хранит ответ целиком: статус, заголовки и тело.
Запрос, на который оно ответило, помечен в списке меткой Rule, и сразу видно,
что правило сработало. Чаще всего при подмене правило просто не совпадает: не
тот путь, в шаблоне остался параметр адреса, или приложение показывает данные из
кэша.
Полный справочник: Локальная подмена.
Рядом
- Как посмотреть трафик с iPhone или Android — пошаговоТелефон и компьютер в одной сети Wi-Fi, прокси в настройках сети, корневой сертификат с полным доверием. Четыре шага и шесть причин, по которым они не срабатывают.
- SSE приходит одним куском: буферизация nginxСобытия Server-Sent Events прилетают пачкой вместо потока. Их держат три слоя: proxy_buffering, gzip и само приложение. Как проверить каждый.