83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
|
|
import axios, { AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios';
|
|||
|
|
import { getServerToken } from './server-auth';
|
|||
|
|
|
|||
|
|
type ResponseType<T = any> = {
|
|||
|
|
code: number;
|
|||
|
|
message: string;
|
|||
|
|
data: T;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 服务端请求函数,用于 SSR
|
|||
|
|
* 从 cookies 中获取 token 并添加到 Authorization header
|
|||
|
|
* 如果接口不需要 token(如公开数据),token 会自动省略
|
|||
|
|
*/
|
|||
|
|
async function serverRequest<T = any>(
|
|||
|
|
url: string,
|
|||
|
|
config?: AxiosRequestConfig & {
|
|||
|
|
requireAuth?: boolean; // 是否必须需要 token,默认 false(可选)
|
|||
|
|
}
|
|||
|
|
): Promise<ResponseType<T>> {
|
|||
|
|
const { requireAuth = false, ...requestConfig } = config || {};
|
|||
|
|
|
|||
|
|
// 从 cookies 中获取 token
|
|||
|
|
const token = await getServerToken();
|
|||
|
|
|
|||
|
|
// 如果需要 token 但没有 token,可以选择抛出错误或继续请求
|
|||
|
|
// 这里选择继续请求,让后端决定是否允许访问
|
|||
|
|
if (requireAuth && !token) {
|
|||
|
|
throw new Error('Authentication required');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建 axios 实例
|
|||
|
|
const instance = axios.create({
|
|||
|
|
withCredentials: false,
|
|||
|
|
baseURL: 'http://54.223.196.180:8091',
|
|||
|
|
validateStatus: (status) => {
|
|||
|
|
return status >= 200 && status < 500;
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 设置请求拦截器,添加 token 到 Authorization header
|
|||
|
|
// 与客户端 request.ts 保持一致
|
|||
|
|
// 注意:token 是可选的,用于 SEO 的公开数据可以不带 token
|
|||
|
|
instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
|||
|
|
if (token) {
|
|||
|
|
config.headers.setAuthorization(`Bearer ${token}`);
|
|||
|
|
}
|
|||
|
|
return config;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 处理参数
|
|||
|
|
let data: any;
|
|||
|
|
if (requestConfig && requestConfig?.params) {
|
|||
|
|
const { params } = requestConfig;
|
|||
|
|
data = Object.fromEntries(
|
|||
|
|
Object.entries(params).filter(([, value]) => value !== '')
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('url', url);
|
|||
|
|
|
|||
|
|
// 发起请求
|
|||
|
|
const response = await instance<ResponseType<T>>(url, {
|
|||
|
|
...requestConfig,
|
|||
|
|
params: data,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
return response.data;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 公开数据请求函数(不需要 token)
|
|||
|
|
* 用于 SEO 友好的公开数据接口
|
|||
|
|
*/
|
|||
|
|
export async function publicServerRequest<T = any>(
|
|||
|
|
url: string,
|
|||
|
|
config?: AxiosRequestConfig
|
|||
|
|
): Promise<ResponseType<T>> {
|
|||
|
|
return serverRequest<T>(url, { ...config, requireAuth: false });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default serverRequest;
|