axiosブロッキングはhttpリクエストをカプセル化し、token再送リクエストをリフレッシュする
17188 ワード
プロジェクトの特定のニーズに応じてhttpリクエストを再カプセル化する場合があります.最近、会社でショッピングモールのプロジェクトをしています.私もvueシロなので、ネットで多くの資料を参考にして、需要を解決しました.私のプロジェクトを例にとると、ニーズは次のとおりです.すべてのサーバに対する要求は先に'/GetMaintenanceState'インタフェースにアクセスし、サーバがメンテナンス中であれば要求をブロックし、メンテナンスページにジャンプしてメンテナンス情報を表示する.サーバが実行中の場合は、リクエストを再開します. ログイン後に送信する要求:(ログイン時にインタフェース'Token'を要求し、 私たちのすべてのインタフェースはネットワークの問題を除いて、返される
構想
2つのリクエストがあります.1つはTokenを必要とし、もう1つはTokenを必要としません.ここでは主に第1種について話します.
requestとresponseブロッキングを設定します.サーバの圧力を軽減するために,要求を開始する際にサーバ状態を取得し,localStorageに格納し,10分以内に要求があれば状態を取得しない.requestブロッキングでサーバが実行されているか、
サーバがtokenを生成する過程で、2つの時間があります.1つはtoken失効時間(
カプセル化サーバのメンテナンスステータスを取得する関数
パッケージリフレッシュtokenの関数
ブロッキングの設定
異なるニーズのリクエストをカプセル化するにはaxiosインスタンスを作成することが望ましい(ここでは主に最も複雑なリクエスト)
requestブロッキング:
responseブロッキング:
これは私のこのプロジェクトの場合にのみ、すべてのリクエストが成功し、ErrorTypeコードで区別されているため、responseコールバックで処理されます.
通常の場合、tokenが期限切れになってステータスコード401に戻り、errコールバック中に処理されるべきである.
パッケージング要求
使用
以上のパッケージはこのプロジェクトのニーズに対応しているだけで、あなたに役に立つことを望んでいます.
転載先:https://juejin.im/post/5d2689d2e51d457759648777
access_token
とrefresh_token
をlocalStorageに保存)で、リクエストのたびにカスタムリクエストヘッダAuthorizationを持参します.access_token
が期限切れになった後、refresh_token
でtokenのリフレッシュを再要求し、refresh_token
が期限切れになったらログインページにジャンプしてtokenを再取得します.status
は200(OK)、要求成功IsSuccess
はtrue
、要求失敗IsSuccess
はfalse
です.要求に失敗すると、応答のエラーコードErrorTypeCode
10003-access_token
は存在しないか、期限切れになり、10004-refresh_token
は存在しないか、期限切れになります.構想
2つのリクエストがあります.1つはTokenを必要とし、もう1つはTokenを必要としません.ここでは主に第1種について話します.
requestとresponseブロッキングを設定します.サーバの圧力を軽減するために,要求を開始する際にサーバ状態を取得し,localStorageに格納し,10分以内に要求があれば状態を取得しない.requestブロッキングでサーバが実行されているか、
access_token
があるかを検出し、ない場合はログインページにジャンプします.最も重要なのは、access_token
が期限切れになった場合、responseブロッカーに設定する必要があるtoken再送要求をリフレッシュすることである.サーバがtokenを生成する過程で、2つの時間があります.1つはtoken失効時間(
access_token
失効時間)、1つはtokenリフレッシュ時間(refresh_token
失効時間)です.refresh_token
の有効期限はaccess_token
の有効期限よりも長いに違いありません.access_token
の有効期限が切れた場合、refresh_token
でtokenをリフレッシュできます.カプセル化サーバのメンテナンスステータスを取得する関数
import axios from 'axios';
function getUrl(url) {
if (url.indexOf(baseUrl) === 0) {
return url;
}
url = url.replace(/^\//, '');
url = baseUrl + '/' + url;
return url;
}
function checkMaintenance() {
let status = {};
let url = getUrl('/GetMaintenanceState');
return axios({
url,
method: 'get'
})
.then(res => {
if (res.data.IsSuccess) {
status = {
IsRun: res.data.Value.IsRun, //
errMsg: res.data.Value.MaintenanceMsg //
};
// localStorageSet , ,
localStorageSet('maintenance', status);
//
return Promise.resolve(status);
}
})
.catch(() => {
return Promise.reject();
});
}
パッケージリフレッシュtokenの関数
function getRefreshToken() {
let url = getUrl('/Token');
// token localStorage
let token = JSON.parse(localStorage.getItem('token'));
return axios({
url,
method: 'post',
data: 'grant_type=refresh_token&refresh_token=' + token.refresh_token,
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
//
Authorization: 'Basic xxxxxxxxxxx'
}
})
.then(res => {
if (res.data.IsSuccess) {
var token_temp = {
access_token: res.data.access_token,
refresh_token: res.data.refresh_token
};
localStorage.setItem('token', JSON.stringify(token_temp));
// access_token session
sessionStorage.setItem('access_token', res.data.access_token);
return Promise.resolve();
}
})
.catch(() => {
return Promise.reject();
});
}
ブロッキングの設定
異なるニーズのリクエストをカプセル化するにはaxiosインスタンスを作成することが望ましい(ここでは主に最も複雑なリクエスト)
requestブロッキング:
import router from '../router';
import { Message } from 'element-ui';
const instance = axios.create();
instance.interceptors.request.use(
config => {
// ,localStorageGet , 10 false
let maintenance = localStorageGet('maintenance');
// maintenance 10 ,
if (!maintenance) {
return checkMaintenance()
.then(res => {
if (res.IsRun) {
// session access_token
let access_token = sessionStorage.getItem('access_token');
// ,
if (!access_token) {
router.push({
path: '/login',
query: { redirect: router.currentRoute.fullPath }
});
//
return Promise.reject();
} else {
config.headers.Authorization = `bearer ${access_token}`;
}
config.headers['Content-Type'] = 'application/json;charset=UTF-8';
//
return config;
} else {
// , ,
router.push({
path: '/maintenance',
query: { redirect: res.errMsg }
});
return Promise.reject();
}
})
.catch(() => {
//
return Promise.reject();
});
} else { // maintenance
if (maintenance.IsRun) {
let access_token = sessionStorage.getItem('access_token');
if (!access_token) {
router.push({
path: '/login',
query: { redirect: router.currentRoute.fullPath }
});
return Promise.reject();
} else {
config.headers.Authorization = `bearer ${access_token}`;
}
config.headers['Content-Type'] = 'application/json;charset=UTF-8';
return config;
} else {
router.push({
path: '/maintenance',
query: { redirect: maintenance.errMsg }
});
return Promise.reject();
}
}
},
err => {
// err , ,
return Promise.reject(err);
}
);
responseブロッキング:
これは私のこのプロジェクトの場合にのみ、すべてのリクエストが成功し、ErrorTypeコードで区別されているため、responseコールバックで処理されます.
通常の場合、tokenが期限切れになってステータスコード401に戻り、errコールバック中に処理されるべきである.
instance.interceptors.response.use(
response => {
// access_token
if (response.data.ErrorTypeCode === 10003) {
return getRefreshToken()
.then(() => {
//
let access_token = sessionStorage.getItem('access_token');
config.headers.Authorization = `bearer ${access_token}`;
config.headers['Content-Type'] = 'application/json;charset=UTF-8';
//
// refresh_token
return instance(config).then(res => {
if (res.data.ErrorTypeCode === 10004) {
router.push({
path: '/login',
query: { redirect: router.currentRoute.fullPath }
});
return Promise.reject();
}
// data
return Promise.resolve(response.data);
});
})
.catch(() => {
// refreshtoken
router.push({
path: '/login',
query: { redirect: router.currentRoute.fullPath }
});
return Promise.reject();
});
}
// refresh_token
if (response.data.ErrorTypeCode == 10004) {
router.push({
path: '/login',
query: { redirect: router.currentRoute.fullPath }
});
return Promise.reject();
}
// data
return response.data;
},
err => {
return Promise.reject(err);
}
);
パッケージング要求
function request({ url, method, Value = null }) {
url = getUrl(url);
method = method.toLowerCase() || 'get';
let obj = {
method,
url
};
if (Value !== null) {
if (method === 'get') {
obj.params = { Value };
} else {
obj.data = { Value };
}
}
return instance(obj)
.then(res => {
return Promise.resolve(res);
})
.catch(() => {
Message.error(' , ');
return Promise.reject();
});
}
//
export function get(setting) {
setting.method = 'GET';
return request(setting);
}
export function post(setting) {
setting.method = 'POST';
return request(setting);
}
使用
import { post, get } from '@/common/network';
post({
url: '/api/xxxxx',
Value: {
GoodsName,
GoodsTypeId
}
}).then(res => {
//.....
})
以上のパッケージはこのプロジェクトのニーズに対応しているだけで、あなたに役に立つことを望んでいます.
転載先:https://juejin.im/post/5d2689d2e51d457759648777