HM-83. Добавлены классы для работы с авторизацией (#36)

This commit is contained in:
Nikolay
2020-07-30 08:32:56 +03:00
committed by GitHub
parent a9282a38e5
commit d957d2d208
6 changed files with 321 additions and 3 deletions

109
src/api/HttpAuthAPI.js Normal file
View File

@ -0,0 +1,109 @@
import axios from 'axios';
import authServiceApi from './AuthServiceAPI';
import tokenApi from './TokenAPI';
/**
* @interface RequestConfig
* @type {Object}
* @property {MethodType} method - метод запроса
* @property {string} url - адрес запроса
* @property {Object} body - тело запроса
*/
/**
* Api прикрепляет ко всем запросом заголовок с токеном авторизации. В случае, когда сервер
* @class HttpAuthApi
*/
class HttpAuthApi {
constructor () {
this.pendingRequests = [];
this.isPendingRefresh = false;
}
/**
* Выполняет какое-то действие над всеми запросами из очереди, пока она не закончится
* @param {Function} handler - функция обработчик запроса
*/
processPendingRequests = (handler) => {
this.isPendingRefresh = false;
while (this.pendingRequests.length) {
const pendingRequest = this.pendingRequests.shift();
handler(pendingRequest);
}
}
/**
* Повторяет все запросы из очереди в порядке их поступления
*/
repeatRequests = () => {
this.processPendingRequests(({resolve, reject, requestConfig}) => {
this.request(requestConfig)
.then(resolve)
.catch(reject);
});
}
/**
* Выбрасывает ошибки для всех запросов из очереди
* @param {axios.error} error - ошибка, которую возвращает axios
*/
rejectRequests = (error) => {
this.processPendingRequests(({reject}) => {
reject(error);
});
}
/**
* Перехватывает ошибку 401 (Не авторизован), другие ошибки выбрасывает дальше
* @param {axios.error} error - ошибка, которую возвращает axios
* @param {Function} resolve - функция промиса, которая разрешает его успешно
* @param {Function} reject - функция промиса, которая завершает его неудачей
* @param {RequestConfig} requestConfig - настройки для выполнения запроса
*/
errorHandling = (error, resolve, reject, requestConfig) => {
if (error.response.status === 401) {
this.isPendingRefresh = true;
this.pendingRequests({resolve, reject, requestConfig});
authServiceApi.refresh()
.then(() => {
this.repeatRequests();
})
.catch((refreshError) => {
this.rejectRequests(refreshError);
/*
* Снять авторизацию и сделать роут
* Сбросить все запросы с ошибкой авторизации
*/
});
} else {
reject(error);
}
}
/**
* Добавляет к запросу токен в качестве заголовка
* @param {RequestConfig} requestConfig - настройки для выполнения запроса
*/
addTokenToRequest = (requestConfig) => ({
...requestConfig,
headers: {
'Authorization': tokenApi.getAccessToken(),
},
})
/**
* Метод для внешнего использования, выполняет запрос к серверу, используя axios
* @param {RequestConfig} requestConfig - настройки для выполнения запроса
*/
request = (requestConfig) => {
return new Promise((resolve, reject) => {
axios(this.addTokenToRequest(requestConfig))
.then((response) => resolve(response))
.catch((error) => this.errorHandling(error, resolve, reject, requestConfig));
});
}
}
const httpAuthApi = new HttpAuthApi();
export default httpAuthApi;