Як я створив open-source HTTP client для service-to-service комунікації

У якийсь момент я зловив себе на думці, що майже в кожному проєкті пишу одне й те саме.

Серйозно — знову і знову:

  • HTTP-клієнт
  • retry
  • auth
  • логування
  • обробка помилок

І кожен раз це трохи інша реалізація і наче все знайоме, але по факту — це новий велосипед.

Проблема, яка повторюється в кожному проєкті

Я працюю з Node.js + TypeScript, часто це мікросервіси або якісь інтеграції.

І майже в кожному проєкті є одна й та сама задача — нормально комунікувати між сервісами.

На словах це звучить дуже просто: «ну зробити HTTP-запит і все».

Але потім починається реальність:

  • що робити, якщо сервіс тимчасово не відповідає?
  • як правильно зробити retry (а не просто «повторити ще раз»)?
  • куди засунути auth, щоб він не був розмазаний по всьому коду?
  • як виглядають нормальні помилки?
  • що робити з логуванням / трейсінгом?

В результаті зазвичай один із сценаріїв:

  • у кожного сервісу свій «унікальний клієнт»
  • або копіпаст з якогось минулого проєкту
  • або якась бібліотека + обгортка

Чому готові рішення не дуже заходили

Я пробував різне:

  • чистий fetch
  • axios
  • свої обгортки

Воно все працює, без питань. Але постійно виникало відчуття, що чогось не вистачає.

👉 вони не дають передбачуваної поведінки «з коробки»

Наприклад:

  • retry треба вигадувати самому
  • помилки — хто як зробив, так і є
  • hooks або відсутні, або незручні
  • auth часто розмазаний по коду

І в якийсь момент я зрозумів, що вже кілька разів написав майже один і той самий HTTP-клієнт 😅

Тому вирішив винести це в окремий пакет

Так зʼявився dfsync (Data Flow Sync).

Перший пакет — @dfsync/client.

Ідея дуже проста: зробити HTTP client з передбачуваною поведінкою для service-to-service комунікації. Не «універсальний комбайн», а нормальний робочий інструмент.

a lightweight and reliable HTTP client for service-to-service communication in Node.js

Що він робить (коротко)

  • typed responses
  • консистентні помилки
  • auth (Bearer, API key, custom)
  • lifecycle hooks (beforeRequest, afterResponse, onError)
  • retry з конфігурацією
  • таймаути

Але ключове — не список фіч, а те, як вони працюють разом.

Як це виглядає в коді


import { createClient } from '@dfsync/client';

const client = createClient({
  baseUrl: 'https://api.example.com',
  timeout: 5000,
  retry: {
    attempts: 3,
    backoff: 'exponential',
    baseDelayMs: 300,
  },
});

const users = await client.get('/users');

Без додаткових обгорток та магії 🧙.

Про retry (бо це біль)

Retry — це взагалі окрема історія.

Часто це або:

  • самописний код
  • якась стороння бібліотека
  • або «та ладно, і так зійде»

Тут воно просто конфігурується:


retry: {
  attempts: 3,
  backoff: 'exponential',
  baseDelayMs: 300,
}

І ти вже знаєш, як воно поводиться.

Hooks — щоб не ламати клієнт під себе

Ще одна штука, яка мені була важлива — можливість розширювати поведінку без «хаків».


hooks: {
  beforeRequest: async (ctx) => {
    ctx.headers.set('x-request-id', crypto.randomUUID());
  },
}

І далі вже можна додавати:

  • логування
  • трейсінг
  • кастомний auth

...не переписуючи сам клієнт.

Що я намагався зробити

Якщо коротко, то не «ще одну бібліотеку», а щось з нормальними принципами:

  • передбачувана поведінка
  • мінімум зайвого
  • розширюваність через hooks
  • TypeScript як база, а не «додаток зверху»

Поточний стан

Проєкт ще на старті, але базові речі вже є:

  • HTTP client
  • retry
  • auth
  • hooks
  • error handling

Далі хочу додати:

  • логування / метрики
  • retry metadata
  • валідацію відповідей
  • а потім ще щось цікаве...

Якщо цікаво подивитись

⭐ GitHub:

github.com/dfsyncjs/dfsync

📦 NPM:

www.npmjs.com/package/@dfsync/client

LinkedIn сторінка (якщо цікаво слідкувати за розвитком):

https://www.linkedin.com/company/dfsync

Буду радий фідбеку

Особливо якщо ви працюєте з:

  • мікросервісами
  • internal APIs
  • інтеграціями

Цікаво почути:

👉 як ви це зараз вирішуєте

👉 де болить

👉 чого не вистачає в існуючих рішеннях

Висновок

Я не намагаюсь зробити «бібліотеку на всі випадки життя».

Швидше — нормальний, передбачуваний інструмент, який не хочеться переписувати в кожному новому проєкті 🙂

Якщо вам це заходить то буду радий фідбеку та ⭐ на GitHub

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось9
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Проблема знайома. Теж дратує кожен раз городити retry, auth і логування з нуля. Підхід з hooks сподобався — гнучко і без копіпасту. Подивлюся бібліотеку, дякую!

Дякую за відгук! 🙌
Саме через ці речі і зʼявилась ідея dfsync.
Зараз рухаюсь за roadmap, поступово додаю нові можливості.

Підписатись на коментарі