API без привязки к транспорту — RPC через HTTP/WebSocket
Бизнес-логика не знает про сеть. Транспорт меняется (HTTP → WebSocket → IPC) без переписывания функций.
Что это
Идеальный API — это набор асинхронных функций, которые работают и на клиенте, и на сервере, и не зависят от того, как они вызываются. Транспорт — отдельный слой, который маршалит вызов в сетевой запрос.
Это RPC-подход: на клиенте лежит «представитель» серверной функции; вызов выглядит как обычный await api.method(args).
API / Пример
// api/createCircle.js — серверная функция
module.exports = async ({ x, y, r }) => {
const id = nextId;
shapes.set(id, { type: 'circle', x, y, r });
return { id };
};
// server — endpoint выдаёт список функций
// клиент построит зеркальный объект API
const api = {};
for (const name of methodNames) {
api[name] = async (args) => {
const res = await fetch(`/api/${name}`, {
method: 'POST',
body: JSON.stringify(args)
});
return res.json();
};
}
// Бизнес-код одинаков на клиенте и сервере
const circle = await api.createCircle({ x: 100, y: 100, r: 50 });
Принципы
- Все экспортируемые функции async — единый контракт, прозрачность.
- Функции не знают про сеть — никакого
req/resвнутри логики. - Каждая функция = один файл — легко найти, легко тестировать.
- Endpoint со списком функций — клиент сам строит зеркальный объект.
- throw → reject — ошибки летят к вызывающему как rejected promise.
- Транспорт — отдельный слой — HTTP/WebSocket/IPC меняются без правок логики.
Производительность / Подводные камни
- Сериализация JSON — большие объекты приходят частями (chunks); собирать на сервере и на клиенте.
- Прозрачность через прокси —
new Proxy({}, { get: (_, name) => (args) => call(name, args) })даёт API без явного списка методов. - Версионирование — добавил параметр → старый клиент не знает; нужны валидаторы и default-значения.
- HTTP overhead на RPC — для частых вызовов лучше WebSocket с мультиплексированием стримов (как Metacom).
fetch/http.requestсовместимы — клиентский полифилfetchна XHR в браузере и нода-fetchповерхhttp.getдают одинаковый контракт.
🎓 Источники
-
🎓 Разработка API на Node.js (клиент и сервер) · 2019-03-28
- Тезисы: API без зависимостей и без привязки к транспорту; все функции async; throw в async = reject; endpoint отдаёт список функций; клиент строит зеркальный объект; функция-«представитель» серверной функции на клиенте; код гуляет между клиентом и сервером.
- Цитата: «Заметьте, что во всех этих функциях я ничего не знаю про сеть вообще. Все эти функции могут исполняться и на клиенте, и на сервере, независимо от протокола.»
-
🎓 HTTP requests in browser and Node.js: XMLHttpRequest, fetch · 2019-03-21
- Тезисы: полифил
fetchповерхhttp.get/https.getна сервере; клиентскийfetchчерез XHR с тем же контрактом; обёртка XHR в Promise; abstraction layer над HTTP — бизнес-код не знает про HTTP-вызовы.
- Тезисы: полифил
-
🎓 Metacom — сеть прозрачна для API при выборе транспорта HTTP, HTTPS, HTTP2, WebSocket · 2025-12-11
- Тезисы: один API-контракт, разные транспорты подбираются автоматически; HTTP/2, WebSocket, HTTPS — выбор по доступности; мультиплексация стримов в одном TCP.