---
# System prepended metadata

title: lido fetch module

---

# lido fetch module

В данном документе я хочу описать видение модуля fetch для фреймворка nestjs.

### Введение
Стоит начать с того, что важно рассказать почему мы пишем свой модуль и какую проблему мы решаем.
Перед нами стояла задача создать легко внедряемый и переиспользуемый модуль для отправки http-запросов со следующими требованиями:
1. Встроенный раунд-робин ротатор для отправки запросов на несколько разных ендпоинтов для повышения отказоустойчивости
2. Гибкая система, которая позволяет отслеживать продолжительность отправки запроса путем внедрения логов и метрик
3. Простая логика ретраев
4. Аборт-контроллер (таймауты)
5. Гибкая логика ретраев (по кастомным параметрам ответа)

На данный момент реализовано только 3 первых пункта, но не полностью.

Для решения этой задачи я хочу представить улучшенную концепцепцию

### Подход на мидлварах
Данный подход строится на похожем принципе как серверный фреймворк koa, только от обратного: у нас есть запрос, получив его мы можем мутировать его набором кастомных функций.

middleware1 -> middleware2 -> fetch -> middleware2 -> middleware1

Пример использования сервиса с мидлварами

- В момент вызова метода
```ts
fetchService.fetchJson<{ test: 1 }>(url, {
    middlewares: [timeout(100)],
})
```
- В момент иницилизации модуля, мидлвара глобальная

```ts
FetchModule.forRoot({
  middlewares: [
    timeout(100)
  ],
});
```

В данном примере мы используем мидлвар `timeout`. Его задача выбросить ошибку в случае выхода за пределы временного лимита.

Ниже представлен код самого мидлвара (на данный момент это прототип, в релизной версии код будет минималистичнее)

```ts
export const timeout =
  (ms: number): CustomMiddleware =>
  async (next, payload) => {
    const res = await next();
    if (!payload?.abortController) return next();
    const timer = setTimeout(() => {
      payload.abortController?.abort();
    }, ms);
    timer.unref();
    return res;
  };
```

