Skip to content

Commit 86b7bc8

Browse files
committed
feat(http): 新增axios封装类及使用示例
新增`Http`类封装axios实例,支持请求拦截器、响应拦截器及带token的请求。同时添加`axios-example.ts`文件,展示如何使用封装好的HTTP请求方法
1 parent d10896b commit 86b7bc8

2 files changed

Lines changed: 230 additions & 0 deletions

File tree

blog-web/src/lib/axios-example.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import http from './axios';
2+
3+
/**
4+
* 示例:如何使用封装好的HTTP请求方法
5+
* 注意:baseURL已在axios.ts中设置为http://121.62.28.11:8080/api
6+
* 所以这里只需要提供相对路径即可
7+
*/
8+
9+
// 示例1:发送GET请求到 http://121.62.28.11:8080/api/test
10+
async function getExample() {
11+
try {
12+
// 只需提供相对路径'/test',不需要完整URL
13+
const response = await http.get('/test');
14+
console.log('GET请求响应:', response);
15+
return response;
16+
} catch (error) {
17+
console.error('GET请求失败:', error);
18+
throw error;
19+
}
20+
}
21+
22+
// 示例2:发送POST请求到 http://121.62.28.11:8080/api/users
23+
async function postExample() {
24+
try {
25+
const data = {
26+
username: 'test_user',
27+
email: 'test@example.com'
28+
};
29+
// 只需提供相对路径'/users',不需要完整URL
30+
const response = await http.post('/users', data);
31+
console.log('POST请求响应:', response);
32+
return response;
33+
} catch (error) {
34+
console.error('POST请求失败:', error);
35+
throw error;
36+
}
37+
}
38+
39+
// 示例3:发送带认证token的GET请求
40+
async function getWithTokenExample() {
41+
try {
42+
// 通过withToken参数指定是否需要在请求头中添加token
43+
const response = await http.get('/user/profile', {}, { withToken: true });
44+
console.log('带Token的GET请求响应:', response);
45+
return response;
46+
} catch (error) {
47+
console.error('带Token的GET请求失败:', error);
48+
throw error;
49+
}
50+
}
51+
52+
// 导出示例函数
53+
export {
54+
getExample,
55+
postExample,
56+
getWithTokenExample
57+
};

blog-web/src/lib/axios.ts

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import axios, {
2+
type AxiosInstance,
3+
type AxiosRequestConfig,
4+
type AxiosResponse,
5+
} from "axios";
6+
7+
// 定义请求配置接口,扩展AxiosRequestConfig以支持可选的withToken参数
8+
interface RequestConfig extends AxiosRequestConfig {
9+
withToken?: boolean; // 是否在请求中包含token
10+
}
11+
12+
// 定义响应数据的通用接口
13+
interface ApiResponse<T = any> {
14+
code: number;
15+
data: T;
16+
message: string;
17+
}
18+
19+
/**
20+
* HTTP请求类,封装axios实例
21+
* 支持Astro按需渲染时选择是否传入token
22+
*/
23+
class Http {
24+
private instance: AxiosInstance;
25+
private baseURL: string;
26+
27+
constructor(baseURL: string = "http://121.62.28.11:8080/api") {
28+
this.baseURL = baseURL;
29+
this.instance = axios.create({
30+
baseURL,
31+
timeout: 10000,
32+
headers: {
33+
"Content-Type": "application/json",
34+
},
35+
});
36+
37+
this.setupInterceptors();
38+
}
39+
40+
/**
41+
* 设置请求和响应拦截器
42+
*/
43+
private setupInterceptors(): void {
44+
// 请求拦截器
45+
this.instance.interceptors.request.use(
46+
(config) => {
47+
const requestConfig = config as RequestConfig;
48+
49+
// 只有当withToken为true时才添加token
50+
if (requestConfig.withToken) {
51+
const token = this.getToken();
52+
if (token) {
53+
config.headers["Authorization"] = `Bearer ${token}`;
54+
}
55+
}
56+
57+
return config;
58+
},
59+
(error) => {
60+
return Promise.reject(error);
61+
},
62+
);
63+
64+
// 响应拦截器
65+
this.instance.interceptors.response.use(
66+
(response: AxiosResponse) => {
67+
return response.data;
68+
},
69+
(error) => {
70+
// 处理错误响应
71+
if (error.response) {
72+
// 服务器返回了错误状态码
73+
const { status } = error.response;
74+
75+
// 处理特定状态码
76+
if (status === 401) {
77+
// 未授权,可以在这里处理登出逻辑
78+
console.error("未授权访问,请重新登录");
79+
} else if (status === 403) {
80+
console.error("没有权限访问该资源");
81+
} else if (status === 404) {
82+
console.error("请求的资源不存在");
83+
} else if (status >= 500) {
84+
console.error("服务器错误,请稍后再试");
85+
}
86+
} else if (error.request) {
87+
// 请求已发送但没有收到响应
88+
console.error("网络错误,无法连接到服务器");
89+
} else {
90+
// 请求配置出错
91+
console.error("请求配置错误:", error.message);
92+
}
93+
94+
return Promise.reject(error);
95+
},
96+
);
97+
}
98+
99+
/**
100+
* 获取存储的token
101+
* 在客户端从localStorage获取,在服务端可能需要从其他地方获取
102+
*/
103+
private getToken(): string | null {
104+
// 检查是否在浏览器环境
105+
if (typeof window !== "undefined") {
106+
return localStorage.getItem("token");
107+
}
108+
// 在服务端渲染时返回null
109+
return null;
110+
}
111+
112+
/**
113+
* 发送GET请求
114+
* @param url 请求地址
115+
* @param params 查询参数
116+
* @param config 请求配置,包含withToken选项
117+
*/
118+
public async get<T = any>(
119+
url: string,
120+
params?: any,
121+
config: RequestConfig = {},
122+
): Promise<ApiResponse<T>> {
123+
return this.instance.get(url, { ...config, params });
124+
}
125+
126+
/**
127+
* 发送POST请求
128+
* @param url 请求地址
129+
* @param data 请求体数据
130+
* @param config 请求配置,包含withToken选项
131+
*/
132+
public async post<T = any>(
133+
url: string,
134+
data?: any,
135+
config: RequestConfig = {},
136+
): Promise<ApiResponse<T>> {
137+
return this.instance.post(url, data, config);
138+
}
139+
140+
/**
141+
* 发送PUT请求
142+
* @param url 请求地址
143+
* @param data 请求体数据
144+
* @param config 请求配置,包含withToken选项
145+
*/
146+
public async put<T = any>(
147+
url: string,
148+
data?: any,
149+
config: RequestConfig = {},
150+
): Promise<ApiResponse<T>> {
151+
return this.instance.put(url, data, config);
152+
}
153+
154+
/**
155+
* 发送DELETE请求
156+
* @param url 请求地址
157+
* @param config 请求配置,包含withToken选项
158+
*/
159+
public async delete<T = any>(
160+
url: string,
161+
config: RequestConfig = {},
162+
): Promise<ApiResponse<T>> {
163+
return this.instance.delete(url, config);
164+
}
165+
}
166+
167+
// 创建默认实例
168+
const http = new Http();
169+
170+
export default http;
171+
172+
// 导出类型和类,方便创建自定义实例
173+
export { Http, type ApiResponse, type RequestConfig };

0 commit comments

Comments
 (0)