mirror of https://github.com/msgbyte/tailchat
refactor: login request
parent
6a0852123a
commit
f99297ce68
@ -0,0 +1,62 @@
|
||||
import axios from 'axios';
|
||||
import _get from 'lodash/get';
|
||||
import _isString from 'lodash/isString';
|
||||
import _isNil from 'lodash/isNil';
|
||||
import _isFunction from 'lodash/isFunction';
|
||||
import { config } from '../config';
|
||||
import { getErrorHook, tokenGetter } from '../manager/request';
|
||||
|
||||
export type CommonRequestResult<T> =
|
||||
| ({
|
||||
result: false;
|
||||
msg: string;
|
||||
} & Partial<T>) // 并上一个T是为了方便取值, 但需要判定
|
||||
| ({
|
||||
result: true;
|
||||
} & T);
|
||||
|
||||
class RequestError extends Error {}
|
||||
|
||||
/**
|
||||
* 创建请求实例
|
||||
*/
|
||||
export function createRequest() {
|
||||
const ins = axios.create({
|
||||
baseURL: config.serverUrl,
|
||||
});
|
||||
|
||||
ins.interceptors.request.use(async (val) => {
|
||||
if (
|
||||
['post', 'get'].includes(String(val.method).toLowerCase()) &&
|
||||
!val.headers['X-Token']
|
||||
) {
|
||||
// 任何请求都尝试增加token
|
||||
val.headers['X-Token'] = await tokenGetter();
|
||||
}
|
||||
|
||||
return val;
|
||||
});
|
||||
|
||||
ins.interceptors.response.use(
|
||||
(val) => {
|
||||
return val;
|
||||
},
|
||||
(err) => {
|
||||
// 尝试获取错误信息
|
||||
const errorMsg: string = _get(err, 'response.data.message');
|
||||
const code: number = _get(err, 'response.data.code');
|
||||
if (_isFunction(getErrorHook)) {
|
||||
const isContinue = getErrorHook(err);
|
||||
if (isContinue === false) {
|
||||
return { data: { result: false, msg: errorMsg, code } };
|
||||
}
|
||||
}
|
||||
|
||||
throw new RequestError(errorMsg ?? err.message);
|
||||
}
|
||||
);
|
||||
|
||||
return ins;
|
||||
}
|
||||
|
||||
export const request = createRequest();
|
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Pawchat 共享配置
|
||||
*/
|
||||
|
||||
export const config = {
|
||||
serverUrl: 'http://127.0.0.1:11000',
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
import { buildRegFn, buildCachedRegFn } from './buildRegFn';
|
||||
|
||||
export const [getErrorHook, setErrorHook] = buildRegFn<(err: any) => boolean>(
|
||||
'requestErrorHook',
|
||||
() => true
|
||||
);
|
||||
|
||||
export const [tokenGetter, setTokenGetter] =
|
||||
buildCachedRegFn<() => Promise<string>>('requestTokenGetter');
|
@ -0,0 +1,15 @@
|
||||
import { request } from '../api/request';
|
||||
|
||||
/**
|
||||
* 邮箱登录
|
||||
* @param email 邮箱
|
||||
* @param password 密码
|
||||
*/
|
||||
export async function loginWithEmail(email: string, password: string) {
|
||||
const data = await request.post('/api/user/login', {
|
||||
email,
|
||||
password,
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
@ -1,4 +1,9 @@
|
||||
import { buildStorage, setStorage } from 'pawchat-shared';
|
||||
import { buildStorage, setStorage, setTokenGetter } from 'pawchat-shared';
|
||||
import { getUserJWT } from './utils/jwt-helper';
|
||||
|
||||
const webStorage = buildStorage(window.localStorage);
|
||||
setStorage(() => webStorage);
|
||||
|
||||
setTokenGetter(async () => {
|
||||
return await getUserJWT();
|
||||
});
|
||||
|
@ -0,0 +1,69 @@
|
||||
import _isObject from 'lodash/isObject';
|
||||
import _get from 'lodash/get';
|
||||
import _isNull from 'lodash/isNull';
|
||||
import _isNil from 'lodash/isNil';
|
||||
import jwtDecode from 'jwt-decode';
|
||||
import { getStorage } from 'pawchat-shared';
|
||||
|
||||
/**
|
||||
* 获取完整jwt字符串的载荷信息(尝试解析json)
|
||||
* @param jwt 完整的jwt字符串
|
||||
*/
|
||||
export function getJWTPayload<T>(jwt: string): Partial<T> {
|
||||
try {
|
||||
const decoded = jwtDecode<T>(jwt);
|
||||
return decoded;
|
||||
} catch (e) {
|
||||
console.error(`getJWTInfo Error: [jwt: ${jwt}]`, e);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// JWT的内存缓存
|
||||
let _userJWT: string | null = null;
|
||||
|
||||
/**
|
||||
* 设置用户登录标识
|
||||
*/
|
||||
export async function setUserJWT(jwt: string): Promise<void> {
|
||||
_userJWT = jwt; // 更新内存中的缓存
|
||||
|
||||
await getStorage().set('jsonwebtoken', jwt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户登录标识
|
||||
*/
|
||||
export async function getUserJWT(): Promise<string> {
|
||||
if (_isNull(_userJWT)) {
|
||||
const jwt = await getStorage().get('jsonwebtoken');
|
||||
_userJWT = jwt; // 将其缓存到内存中
|
||||
|
||||
return jwt;
|
||||
}
|
||||
return _userJWT;
|
||||
}
|
||||
|
||||
export interface JWTUserInfoData {
|
||||
name?: string;
|
||||
uuid?: string;
|
||||
avatar?: string;
|
||||
}
|
||||
/**
|
||||
* 获取token中的明文信息
|
||||
* 明确需要返回一个对象
|
||||
*/
|
||||
export async function getJWTUserInfo(): Promise<JWTUserInfoData> {
|
||||
try {
|
||||
const token = await getUserJWT();
|
||||
const info = getJWTPayload(token);
|
||||
if (_isObject(info)) {
|
||||
return info;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('getJWTInfo Error:', e);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
Loading…
Reference in New Issue