visual-novel-web/src/lib/server-request.ts

83 lines
2.2 KiB
TypeScript
Raw Normal View History

2025-11-03 10:03:34 +00:00
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
* tokentoken
*/
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;