create authAxios and normalAxios instance

This commit is contained in:
秦秋旭 2023-02-28 02:52:35 +08:00
parent 3a3f427daa
commit 375e1ab4e5
7 changed files with 117 additions and 79 deletions

View File

@ -1,6 +1,22 @@
import axios from '@/utils/axios'
import { EmailSendDto, EmailSendResponse } from './email.interface'
import { authAxios, normalAxios } from '@/utils/axios'
import {
EmailSendDto,
EmailSendResponse,
EmailVerifyCodeScene,
} from './email.interface'
export async function sendEmailVerifyCode(params: EmailSendDto) {
return axios.get<EmailSendResponse>('/api/email/verifyCode', { params })
if (
[
EmailVerifyCodeScene.register,
EmailVerifyCodeScene.forgetPassword,
].includes(params.scene)
) {
return normalAxios.get<EmailSendResponse>('/api/email/verifyCode', {
params,
})
}
return authAxios.get<EmailSendResponse>('/api/email/verifyCode', {
params,
})
}

View File

@ -1,5 +1,4 @@
import axios from '@/utils/axios'
import { type AxiosResponse } from 'axios'
import { authAxios, normalAxios } from '@/utils/axios'
import {
LoginInputDto,
RegisterInputDto,
@ -10,35 +9,25 @@ import {
} from './user.interface'
export async function register(data: RegisterInputDto) {
return axios.post<AccessToken>('/api/users', data)
return normalAxios.post<AccessToken>('/api/users', data)
}
export async function login(data: LoginInputDto) {
return axios.post<AccessToken>('/api/users/token', data)
}
export async function logout() {
return axios.delete('/api/users/me/token')
return normalAxios.post<AccessToken>('/api/users/token', data)
}
export async function forgetPassword(data: ForgetPasswordInputDto) {
return axios.patch<AccessToken>('/api/users/password', data)
return normalAxios.patch<AccessToken>('/api/users/password', data)
}
export async function logout() {
return authAxios.delete('/api/users/me/token')
}
export async function deleteUser(data: DeleteUser) {
return axios.delete('/api/users/me', { data })
}
let refreshing: Promise<AxiosResponse<AccessToken>> | null
export async function refreshToken() {
if (!refreshing) {
refreshing = axios.put<AccessToken>('/api/users/me/token').finally(() => {
refreshing = null
})
}
return refreshing
return authAxios.delete('/api/users/me', { data })
}
export async function getUserInfo() {
return axios.get<User>('/api/users/me')
return authAxios.get<User>('/api/users/me')
}

View File

@ -1,55 +0,0 @@
import axios, { type AxiosError } from 'axios'
import Router from 'next/router'
import status from 'http-status'
import * as api from '@/api'
import { toast } from 'react-toastify'
interface ErrorResponse {
statusCode: number
message: string
}
const throwError = (error: AxiosError<ErrorResponse>) => {
toast.error(
error.response?.data.message.toString() ?? error.response?.statusText,
)
return Promise.reject(error)
}
axios.interceptors.request.use(function (config) {
const accessToken = localStorage.getItem('accessToken')
config.headers.Authorization = `Bearer ${accessToken}`
return config
})
axios.interceptors.response.use(
function (response) {
return response
},
async function (error: AxiosError<ErrorResponse>) {
// fail to refresh token
if (
error.config &&
error.config.url === '/api/users/me/token' &&
error.config.method === 'put'
) {
Router.push('/login')
return throwError(error)
}
switch (error.response?.status) {
case status.UNAUTHORIZED: {
if (error.config?.url === '/api/users/token') {
throw throwError(error)
}
const res = await api.user.refreshToken()
localStorage.setItem('accessToken', res.data)
return error.config && axios.request(error.config)
}
default: {
return throwError(error)
}
}
},
)
export default axios

View File

@ -0,0 +1,53 @@
import axios, { AxiosError, type AxiosResponse } from 'axios'
import Router from 'next/router'
import status from 'http-status'
import { AccessToken } from '@/api/user.interface'
import { throwError, ErrorResponse } from './throwError'
import normalAxios from './normalAxios'
/** 需要Authorization的axios */
const authAxios = axios.create()
authAxios.interceptors.request.use(function (config) {
const accessToken = localStorage.getItem('accessToken')
config.headers.Authorization = `Bearer ${accessToken}`
return config
})
authAxios.interceptors.response.use(
(response) => response,
async (error: AxiosError<ErrorResponse>) => {
switch (error.response?.status) {
case status.UNAUTHORIZED: {
const res = await refreshToken()
localStorage.setItem('accessToken', res.data)
return error.config && axios.request(error.config)
}
default: {
return throwError(error)
}
}
},
)
const refreshToken = (() => {
let refreshingToken: Promise<AxiosResponse<AccessToken>> | null = null
return async function () {
if (!refreshingToken) {
refreshingToken = normalAxios
.put<AccessToken>('/api/users/me/token')
.finally(() => {
refreshingToken = null
})
}
refreshingToken?.catch((error) => {
if (error instanceof AxiosError) {
Router.push('/login')
throwError(error)
}
})
return refreshingToken
}
})()
export default authAxios

4
src/utils/axios/index.ts Normal file
View File

@ -0,0 +1,4 @@
import authAxios from './authAxios'
import normalAxios from './normalAxios'
export { authAxios, normalAxios }

View File

@ -0,0 +1,17 @@
import axios, { AxiosError } from 'axios'
import { throwError, ErrorResponse } from './throwError'
const normalAxios = axios.create()
normalAxios.interceptors.response.use(
(response) => response,
async (error: AxiosError<ErrorResponse>) => {
switch (error.response?.status) {
default: {
return throwError(error)
}
}
},
)
export default normalAxios

View File

@ -0,0 +1,14 @@
import { AxiosError } from 'axios'
import { toast } from 'react-toastify'
export interface ErrorResponse {
statusCode: number
message: string
}
export const throwError = (error: AxiosError<ErrorResponse>) => {
toast.error(
error.response?.data.message.toString() ?? error.response?.statusText,
)
return Promise.reject(error)
}