HM-83. Добавлены классы для работы с авторизацией (#36)
This commit is contained in:
109
src/api/HttpAuthAPI.js
Normal file
109
src/api/HttpAuthAPI.js
Normal 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;
|
||||
Reference in New Issue
Block a user