Демонстрационный проект для показа работы автоматического обновления токенов при 401 ошибках.
- ✅ Перехват 401 ошибок для REST (Axios) и GraphQL (Apollo) запросов
- ✅ Фоновое обновление токена без прерывания работы пользователя
- ✅ Повтор упавших запросов после успешного обновления токена
- ✅ Обработка параллельных запросов (только один refresh запрос)
- ✅ Поддержка отмены запросов (AbortController)
- ✅ Готовые пакеты для интеграции в проекты
token-renewal-example/
├── apps/
│ ├── client/ # Vue 3 + TypeScript клиент
│ └── server/ # Express + TypeScript сервер
├── packages/
│ ├── axios-token-renewal/ # Пакет для Axios
│ ├── apollo-token-renewal/ # Пакет для Apollo
│ └── simple-logger/ # Пакет для логирования- Node.js >= 22.12.0 (используйте
nvm useв корне проекта) - Yarn
# Переключитесь на правильную версию Node
nvm use
# Установите все зависимости
yarn install# Соберите пакеты и запустите приложения
yarn start
# Или отдельными командами:
yarn build:packages # Собрать пакеты
yarn serve # Запустить сервер и клиент- Откройте http://localhost:5173
- Войдите с логином
demoи паролемdemo - Тестируйте различные сценарии:
- Обычные запросы
- Параллельные запросы
- Отмена запросов
- "Протухание" токена (слабое/сильное)
# Посмотреть граф зависимостей
yarn graph
# Собрать все проекты
yarn build
# Запустить все в dev режиме
yarn dev
# Собрать конкретный пакет
yarn nx build @packages/axios-token-renewal
# Запустить конкретное приложение
yarn nx serve clientКогда сервер возвращает 401, interceptor/link перехватывает ошибку и проверяет, можно ли обновить токен.
Если уже идёт обновление токена, новые запросы добавляются в очередь и ждут результата.
Выполняется один запрос на обновление токена. При успехе - все запросы из очереди повторяются.
Если токен не удалось обновить (например, при "сильном" протухании), пользователь перенаправляется на страницу входа.
import { setupAxiosTokenRenewal } from '@packages/axios-token-renewal';
setupAxiosTokenRenewal({
refresh: async () => {
// Ваша логика обновления токена
const response = await fetch('/auth/refresh', {
method: 'POST',
credentials: 'include'
});
return response.ok;
},
handlers: {
failure: () => {
// Действия при невозможности обновить токен
router.push('/login');
}
}
}, axiosInstance);import { createTokenRenewalLink } from '@packages/apollo-token-renewal';
const tokenRenewalLink = createTokenRenewalLink({
refresh: async () => {
// Ваша логика обновления токена
const response = await fetch('/auth/refresh', {
method: 'POST',
credentials: 'include'
});
return response.ok;
},
handlers: {
failure: () => {
// Действия при невозможности обновить токен
router.push('/login');
}
}
});
const apolloClient = new ApolloClient({
link: ApolloLink.from([tokenRenewalLink, httpLink]),
cache: new InMemoryCache()
});- Единственный refresh запрос: При множественных 401 ошибках выполняется только один запрос на обновление токена
- Сохранение контекста: Все оригинальные параметры запросов сохраняются и используются при повторе
- Поддержка отмены: Отменённые запросы корректно обрабатываются и не повторяются
- TypeScript: Полная типизация для удобной интеграции
Подробная документация находится в папке docs/:
MIT