@reskin/core 0.0.22 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/reskin-core-directives.umd.js +303 -163
- package/bundles/reskin-core-directives.umd.js.map +1 -1
- package/bundles/reskin-core-guards.umd.js +119 -32
- package/bundles/reskin-core-guards.umd.js.map +1 -1
- package/bundles/reskin-core-interceptors.umd.js +286 -104
- package/bundles/reskin-core-interceptors.umd.js.map +1 -1
- package/bundles/reskin-core-utils.umd.js +220 -77
- package/bundles/reskin-core-utils.umd.js.map +1 -1
- package/directives/auth.directive.d.ts +56 -9
- package/directives/load.styles.directive.d.ts +45 -5
- package/directives/string.template.outlet.directive.d.ts +68 -11
- package/esm2015/directives/auth.directive.js +71 -30
- package/esm2015/directives/load.styles.directive.js +84 -15
- package/esm2015/directives/string.template.outlet.directive.js +118 -60
- package/esm2015/guards/auth.guard.js +117 -30
- package/esm2015/interceptors/blob.interceptor.js +67 -28
- package/esm2015/interceptors/cache.interceptor.js +46 -14
- package/esm2015/interceptors/error.interceptor.js +104 -12
- package/esm2015/interceptors/public-api.js +2 -1
- package/esm2015/interceptors/token.interceptor.js +66 -53
- package/esm2015/interceptors/types.js +5 -0
- package/esm2015/utils/array.js +42 -22
- package/esm2015/utils/dom.js +29 -11
- package/esm2015/utils/form.js +44 -13
- package/esm2015/utils/store.js +101 -26
- package/fesm2015/reskin-core-directives.js +269 -103
- package/fesm2015/reskin-core-directives.js.map +1 -1
- package/fesm2015/reskin-core-guards.js +116 -29
- package/fesm2015/reskin-core-guards.js.map +1 -1
- package/fesm2015/reskin-core-interceptors.js +282 -102
- package/fesm2015/reskin-core-interceptors.js.map +1 -1
- package/fesm2015/reskin-core-utils.js +212 -68
- package/fesm2015/reskin-core-utils.js.map +1 -1
- package/guards/auth.guard.d.ts +85 -5
- package/interceptors/blob.interceptor.d.ts +30 -3
- package/interceptors/cache.interceptor.d.ts +28 -4
- package/interceptors/error.interceptor.d.ts +43 -2
- package/interceptors/public-api.d.ts +1 -0
- package/interceptors/token.interceptor.d.ts +35 -18
- package/interceptors/types.d.ts +68 -0
- package/package.json +1 -1
- package/utils/array.d.ts +8 -1
- package/utils/dom.d.ts +32 -5
- package/utils/form.d.ts +37 -2
- package/utils/store.d.ts +56 -15
|
@@ -2,43 +2,63 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { Injectable } from '@angular/core';
|
|
3
3
|
import { HTTP_INTERCEPTORS, HttpHeaders, HttpEventType, HttpResponse } from '@angular/common/http';
|
|
4
4
|
import * as i1 from '@reskin/core/services';
|
|
5
|
-
import {
|
|
5
|
+
import { throwError, Observable } from 'rxjs';
|
|
6
6
|
import { catchError, shareReplay, switchMap } from 'rxjs/operators';
|
|
7
7
|
import * as i1$1 from '@angular/router';
|
|
8
|
+
import { Router } from '@angular/router';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
/**
|
|
11
|
+
* HTTP 拦截器相关类型定义
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Token 拦截器常量
|
|
16
|
+
*/
|
|
10
17
|
const DEFAULT_TOKEN_HEADER_NAME = 'Authorization';
|
|
11
18
|
const TOKEN_CONTROL_HEADER = 'Token-Control';
|
|
12
19
|
const CUSTOM_TOKEN_HEADER = 'Custom-Token';
|
|
13
20
|
const CUSTOM_TOKEN_HEADER_NAME = 'Custom-Token-Header';
|
|
14
21
|
const AUTH_ID_HEADER = 'X-Auth-Id';
|
|
22
|
+
/**
|
|
23
|
+
* Token 拦截器
|
|
24
|
+
* 自动为 HTTP 请求添加认证 Token
|
|
25
|
+
*/
|
|
15
26
|
class TokenInterceptor {
|
|
16
|
-
constructor(
|
|
17
|
-
this.
|
|
27
|
+
constructor(authService) {
|
|
28
|
+
this.authService = authService;
|
|
18
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* 拦截 HTTP 请求,添加 Token 认证信息
|
|
32
|
+
* @param request HTTP 请求对象
|
|
33
|
+
* @param next 下一个拦截器处理器
|
|
34
|
+
* @returns Observable<HttpEvent<unknown>>
|
|
35
|
+
*/
|
|
19
36
|
intercept(request, next) {
|
|
20
|
-
const
|
|
21
|
-
//
|
|
37
|
+
const tokenControl = request.headers.get(TOKEN_CONTROL_HEADER);
|
|
38
|
+
// 如果明确指定不需要 Token,直接放行
|
|
39
|
+
if (tokenControl === 'no-token') {
|
|
40
|
+
return next.handle(request);
|
|
41
|
+
}
|
|
22
42
|
const customToken = request.headers.get(CUSTOM_TOKEN_HEADER);
|
|
23
|
-
// 检查是否提供了自定义token header名称
|
|
24
43
|
const customTokenHeaderName = request.headers.get(CUSTOM_TOKEN_HEADER_NAME) || DEFAULT_TOKEN_HEADER_NAME;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
const headers = {};
|
|
45
|
+
if (customToken) {
|
|
46
|
+
// 使用自定义 Token
|
|
47
|
+
headers[customTokenHeaderName] = customToken;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// 使用默认认证信息
|
|
51
|
+
const auth = this.authService.token;
|
|
52
|
+
if (auth === null || auth === void 0 ? void 0 : auth.token) {
|
|
53
|
+
headers[DEFAULT_TOKEN_HEADER_NAME] = auth.token;
|
|
54
|
+
if (auth.id) {
|
|
36
55
|
headers[AUTH_ID_HEADER] = auth.id;
|
|
37
56
|
}
|
|
38
57
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
58
|
+
}
|
|
59
|
+
// 如果有需要添加的 Header,克隆请求并添加
|
|
60
|
+
if (Object.keys(headers).length > 0) {
|
|
61
|
+
request = request.clone({ setHeaders: headers });
|
|
42
62
|
}
|
|
43
63
|
return next.handle(request);
|
|
44
64
|
}
|
|
@@ -49,78 +69,141 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImpo
|
|
|
49
69
|
type: Injectable
|
|
50
70
|
}], ctorParameters: function () { return [{ type: i1.RkAuthService }]; } });
|
|
51
71
|
/**
|
|
52
|
-
*
|
|
72
|
+
* 提供 Token 拦截器
|
|
73
|
+
* @returns Provider 配置对象
|
|
53
74
|
*/
|
|
54
75
|
function providerAuthToken() {
|
|
55
76
|
return { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true };
|
|
56
77
|
}
|
|
57
78
|
/**
|
|
58
|
-
*
|
|
59
|
-
* @param urls
|
|
60
|
-
* @param params
|
|
61
|
-
* @
|
|
79
|
+
* 创建不带 Token 的请求配置
|
|
80
|
+
* @param urls 模板字符串数组
|
|
81
|
+
* @param params 模板参数
|
|
82
|
+
* @returns [url, options] 元组
|
|
83
|
+
* @example
|
|
84
|
+
* this.http.get(...NoAuthTokenTemplate`/api/public/data`).subscribe();
|
|
62
85
|
*/
|
|
63
86
|
function NoAuthTokenTemplate(urls, ...params) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
url = String.raw(urls, ...params);
|
|
67
|
-
}
|
|
68
|
-
return [url, { headers: new HttpHeaders({ 'Token-Control': 'no-token' }) }];
|
|
87
|
+
const url = params.length > 0 ? String.raw(urls, ...params) : urls[0];
|
|
88
|
+
return [url, { headers: new HttpHeaders({ [TOKEN_CONTROL_HEADER]: 'no-token' }) }];
|
|
69
89
|
}
|
|
70
90
|
/**
|
|
71
|
-
*
|
|
72
|
-
* @param token 自定义
|
|
73
|
-
* @param urls
|
|
74
|
-
* @param params
|
|
75
|
-
* @
|
|
91
|
+
* 创建使用自定义 Token 的请求配置
|
|
92
|
+
* @param token 自定义 Token 值
|
|
93
|
+
* @param urls 模板字符串数组
|
|
94
|
+
* @param params 模板参数
|
|
95
|
+
* @returns [url, options] 元组
|
|
96
|
+
* @example
|
|
97
|
+
* this.http.get(...CustomTokenTemplate('my-token', `/api/data`)).subscribe();
|
|
76
98
|
*/
|
|
77
99
|
function CustomTokenTemplate(token, urls, ...params) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
url = String.raw(urls, ...params);
|
|
81
|
-
}
|
|
82
|
-
return [url, { headers: new HttpHeaders({ 'Custom-Token': token }) }];
|
|
100
|
+
const url = params.length > 0 ? String.raw(urls, ...params) : urls[0];
|
|
101
|
+
return [url, { headers: new HttpHeaders({ [CUSTOM_TOKEN_HEADER]: token }) }];
|
|
83
102
|
}
|
|
84
103
|
/**
|
|
85
|
-
*
|
|
86
|
-
* @param token 自定义
|
|
87
|
-
* @param headerName 自定义
|
|
88
|
-
* @param urls
|
|
89
|
-
* @param params
|
|
90
|
-
* @
|
|
104
|
+
* 创建使用自定义 Token 和自定义 Header 名称的请求配置
|
|
105
|
+
* @param token 自定义 Token 值
|
|
106
|
+
* @param headerName 自定义 Header 名称
|
|
107
|
+
* @param urls 模板字符串数组
|
|
108
|
+
* @param params 模板参数
|
|
109
|
+
* @returns [url, options] 元组
|
|
110
|
+
* @example
|
|
111
|
+
* this.http.get(...CustomTokenWithHeaderTemplate('my-token', 'X-API-Key', `/api/data`)).subscribe();
|
|
91
112
|
*/
|
|
92
113
|
function CustomTokenWithHeaderTemplate(token, headerName, urls, ...params) {
|
|
93
|
-
|
|
94
|
-
if (params.length > 0) {
|
|
95
|
-
url = String.raw(urls, ...params);
|
|
96
|
-
}
|
|
114
|
+
const url = params.length > 0 ? String.raw(urls, ...params) : urls[0];
|
|
97
115
|
return [
|
|
98
116
|
url,
|
|
99
117
|
{
|
|
100
118
|
headers: new HttpHeaders({
|
|
101
|
-
|
|
102
|
-
|
|
119
|
+
[CUSTOM_TOKEN_HEADER]: token,
|
|
120
|
+
[CUSTOM_TOKEN_HEADER_NAME]: headerName,
|
|
103
121
|
}),
|
|
104
122
|
},
|
|
105
123
|
];
|
|
106
124
|
}
|
|
107
125
|
|
|
126
|
+
/**
|
|
127
|
+
* 默认配置
|
|
128
|
+
*/
|
|
129
|
+
const DEFAULT_CONFIG = {
|
|
130
|
+
unauthorizedPath: '/errors/401',
|
|
131
|
+
enableLogging: false,
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* HTTP 错误拦截器
|
|
135
|
+
* 统一处理 HTTP 请求错误,包括 401 未授权错误的自动跳转
|
|
136
|
+
*/
|
|
108
137
|
class ErrorInterceptor {
|
|
109
138
|
constructor(router) {
|
|
110
139
|
this.router = router;
|
|
140
|
+
this.config = DEFAULT_CONFIG;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* 设置拦截器配置
|
|
144
|
+
* @param config 配置对象
|
|
145
|
+
*/
|
|
146
|
+
setConfig(config) {
|
|
147
|
+
this.config = Object.assign(Object.assign({}, DEFAULT_CONFIG), config);
|
|
111
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* 拦截 HTTP 请求,处理错误响应
|
|
151
|
+
* @param request HTTP 请求对象
|
|
152
|
+
* @param next 下一个拦截器处理器
|
|
153
|
+
* @returns Observable<HttpEvent<unknown>>
|
|
154
|
+
*/
|
|
112
155
|
intercept(request, next) {
|
|
113
|
-
return next.handle(request).pipe(catchError((
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
this.
|
|
156
|
+
return next.handle(request).pipe(catchError((error) => {
|
|
157
|
+
// 处理 401 未授权错误
|
|
158
|
+
if (error.status === 401) {
|
|
159
|
+
this.handleUnauthorizedError();
|
|
160
|
+
return throwError(error);
|
|
117
161
|
}
|
|
118
|
-
|
|
119
|
-
|
|
162
|
+
// 记录错误日志
|
|
163
|
+
if (this.config.enableLogging) {
|
|
164
|
+
console.error('[HTTP Error]', {
|
|
165
|
+
url: request.url,
|
|
166
|
+
method: request.method,
|
|
167
|
+
status: error.status,
|
|
168
|
+
message: error.message,
|
|
169
|
+
error: error.error,
|
|
170
|
+
});
|
|
120
171
|
}
|
|
121
|
-
|
|
172
|
+
// 提取错误信息
|
|
173
|
+
const errorMessage = this.extractErrorMessage(error);
|
|
174
|
+
return throwError(new Error(errorMessage));
|
|
122
175
|
}));
|
|
123
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* 处理 401 未授权错误
|
|
179
|
+
*/
|
|
180
|
+
handleUnauthorizedError() {
|
|
181
|
+
const path = this.config.unauthorizedPath || DEFAULT_CONFIG.unauthorizedPath;
|
|
182
|
+
this.router.navigate([path]).catch((err) => {
|
|
183
|
+
console.error('导航到错误页面失败:', err);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* 提取错误信息
|
|
188
|
+
* @param error HTTP 错误响应
|
|
189
|
+
* @returns 错误信息字符串
|
|
190
|
+
*/
|
|
191
|
+
extractErrorMessage(error) {
|
|
192
|
+
if (error.error) {
|
|
193
|
+
// 尝试从 error.error 中提取信息
|
|
194
|
+
if (typeof error.error === 'string') {
|
|
195
|
+
return error.error;
|
|
196
|
+
}
|
|
197
|
+
if (error.error.msg) {
|
|
198
|
+
return error.error.msg;
|
|
199
|
+
}
|
|
200
|
+
if (error.error.message) {
|
|
201
|
+
return error.error.message;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// 使用默认错误信息
|
|
205
|
+
return error.message || `HTTP Error ${error.status}`;
|
|
206
|
+
}
|
|
124
207
|
}
|
|
125
208
|
ErrorInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: ErrorInterceptor, deps: [{ token: i1$1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
126
209
|
ErrorInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: ErrorInterceptor });
|
|
@@ -128,28 +211,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImpo
|
|
|
128
211
|
type: Injectable
|
|
129
212
|
}], ctorParameters: function () { return [{ type: i1$1.Router }]; } });
|
|
130
213
|
/**
|
|
131
|
-
*
|
|
214
|
+
* 提供 HTTP 错误拦截器
|
|
215
|
+
* @param config 可选的配置对象
|
|
216
|
+
* @returns Provider 配置对象
|
|
217
|
+
* @example
|
|
218
|
+
* providers: [
|
|
219
|
+
* providerHttpError({ unauthorizedPath: '/login', enableLogging: true })
|
|
220
|
+
* ]
|
|
132
221
|
*/
|
|
133
|
-
function providerHttpError() {
|
|
134
|
-
|
|
222
|
+
function providerHttpError(config) {
|
|
223
|
+
if (config) {
|
|
224
|
+
// 如果有配置,使用 useFactory
|
|
225
|
+
return {
|
|
226
|
+
provide: HTTP_INTERCEPTORS,
|
|
227
|
+
useFactory: (router) => {
|
|
228
|
+
const interceptor = new ErrorInterceptor(router);
|
|
229
|
+
interceptor.setConfig(config);
|
|
230
|
+
return interceptor;
|
|
231
|
+
},
|
|
232
|
+
deps: [Router],
|
|
233
|
+
multi: true,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
// 没有配置,直接使用 useClass
|
|
238
|
+
return {
|
|
239
|
+
provide: HTTP_INTERCEPTORS,
|
|
240
|
+
useClass: ErrorInterceptor,
|
|
241
|
+
multi: true,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
135
244
|
}
|
|
136
245
|
|
|
246
|
+
/**
|
|
247
|
+
* 缓存策略标识
|
|
248
|
+
*/
|
|
249
|
+
const CACHE_HEADER = 'Cache-Map';
|
|
250
|
+
const CACHE_STRATEGY = 'Storage';
|
|
251
|
+
/**
|
|
252
|
+
* HTTP 缓存拦截器
|
|
253
|
+
* 为 GET 请求提供缓存功能,减少重复请求
|
|
254
|
+
*/
|
|
137
255
|
class CacheInterceptor {
|
|
138
|
-
constructor(
|
|
139
|
-
this.
|
|
256
|
+
constructor(cacheHttpService) {
|
|
257
|
+
this.cacheHttpService = cacheHttpService;
|
|
140
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* 拦截 HTTP 请求,实现缓存逻辑
|
|
261
|
+
* @param request HTTP 请求对象
|
|
262
|
+
* @param next 下一个拦截器处理器
|
|
263
|
+
* @returns Observable<HttpEvent<unknown>>
|
|
264
|
+
*/
|
|
141
265
|
intercept(request, next) {
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
let
|
|
147
|
-
if (!
|
|
148
|
-
|
|
149
|
-
|
|
266
|
+
// 只缓存 GET 请求且明确标记了缓存策略的请求
|
|
267
|
+
const cacheStrategy = request.headers.get(CACHE_HEADER);
|
|
268
|
+
if (request.method === 'GET' && cacheStrategy === CACHE_STRATEGY) {
|
|
269
|
+
// 尝试从缓存中获取响应
|
|
270
|
+
let cachedResponse = this.cacheHttpService.get(request.url);
|
|
271
|
+
if (!cachedResponse) {
|
|
272
|
+
// 缓存未命中,发起请求并缓存结果
|
|
273
|
+
cachedResponse = next.handle(request).pipe(shareReplay(1));
|
|
274
|
+
this.cacheHttpService.set(request.url, cachedResponse);
|
|
150
275
|
}
|
|
151
|
-
return
|
|
276
|
+
return cachedResponse;
|
|
152
277
|
}
|
|
278
|
+
// 非缓存请求,直接放行
|
|
153
279
|
return next.handle(request);
|
|
154
280
|
}
|
|
155
281
|
}
|
|
@@ -159,58 +285,110 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImpo
|
|
|
159
285
|
type: Injectable
|
|
160
286
|
}], ctorParameters: function () { return [{ type: i1.RkCacheHttpService }]; } });
|
|
161
287
|
/**
|
|
162
|
-
*
|
|
288
|
+
* 提供 HTTP 缓存拦截器
|
|
289
|
+
* @returns Provider 配置对象
|
|
290
|
+
* @example
|
|
291
|
+
* providers: [providerHttpCache()]
|
|
163
292
|
*/
|
|
164
293
|
function providerHttpCache() {
|
|
165
294
|
return { provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true };
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* 创建带缓存标记的 GET 请求配置
|
|
298
|
+
* @param urls 模板字符串数组
|
|
299
|
+
* @param params 模板参数
|
|
300
|
+
* @returns [url, options] 元组
|
|
301
|
+
* @example
|
|
302
|
+
* this.http.get(...CacheHttpTemplate`/api/data`).subscribe();
|
|
303
|
+
*/
|
|
304
|
+
function CacheHttpTemplate(urls, ...params) {
|
|
305
|
+
const url = params.length > 0 ? String.raw(urls, ...params) : urls[0];
|
|
306
|
+
return [url, { headers: new HttpHeaders({ [CACHE_HEADER]: CACHE_STRATEGY }) }];
|
|
166
307
|
}
|
|
167
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Blob 响应拦截器
|
|
311
|
+
* 处理文件下载请求中的 JSON 错误响应
|
|
312
|
+
*/
|
|
168
313
|
class BlobInterceptor {
|
|
314
|
+
/**
|
|
315
|
+
* 拦截 HTTP 请求,处理 Blob 类型响应
|
|
316
|
+
* @param request HTTP 请求对象
|
|
317
|
+
* @param next 下一个拦截器处理器
|
|
318
|
+
* @returns Observable<HttpEvent<T>>
|
|
319
|
+
*/
|
|
169
320
|
intercept(request, next) {
|
|
321
|
+
// 只处理 responseType 为 blob 的请求
|
|
170
322
|
if (request.responseType !== 'blob') {
|
|
171
323
|
return next.handle(request);
|
|
172
324
|
}
|
|
173
|
-
return next.handle(request).pipe(switchMap((
|
|
325
|
+
return next.handle(request).pipe(switchMap((event) => this.handleBlobResponse(event)), catchError((error) => this.handleBlobError(error)));
|
|
174
326
|
}
|
|
175
|
-
|
|
176
|
-
|
|
327
|
+
/**
|
|
328
|
+
* 处理 Blob 响应事件
|
|
329
|
+
* @param event HTTP 事件
|
|
330
|
+
* @returns Observable<HttpEvent<any>>
|
|
331
|
+
*/
|
|
332
|
+
handleBlobResponse(event) {
|
|
333
|
+
var _a;
|
|
334
|
+
// 只处理完整的响应事件
|
|
335
|
+
if (event.type !== HttpEventType.Response) {
|
|
177
336
|
return new Observable((subscriber) => {
|
|
178
|
-
subscriber.next(
|
|
337
|
+
subscriber.next(event);
|
|
179
338
|
subscriber.complete();
|
|
180
339
|
});
|
|
181
340
|
}
|
|
182
|
-
|
|
183
|
-
|
|
341
|
+
// 检查响应体是否为 JSON 类型(通常表示错误)
|
|
342
|
+
if (event instanceof HttpResponse && ((_a = event.body) === null || _a === void 0 ? void 0 : _a.type) === 'application/json') {
|
|
343
|
+
return this.convertBlobToJson(event.body);
|
|
184
344
|
}
|
|
185
345
|
return new Observable((subscriber) => {
|
|
186
|
-
subscriber.next(
|
|
346
|
+
subscriber.next(event);
|
|
187
347
|
subscriber.complete();
|
|
188
348
|
});
|
|
189
349
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
350
|
+
/**
|
|
351
|
+
* 处理 Blob 错误响应
|
|
352
|
+
* @param error HTTP 错误响应
|
|
353
|
+
* @returns Observable<HttpEvent<any>>
|
|
354
|
+
*/
|
|
355
|
+
handleBlobError(error) {
|
|
356
|
+
var _a;
|
|
357
|
+
// 如果错误响应体是 JSON 类型的 Blob,转换为 JSON 对象
|
|
358
|
+
if (((_a = error.error) === null || _a === void 0 ? void 0 : _a.type) === 'application/json') {
|
|
359
|
+
return this.convertBlobToJson(error.error);
|
|
193
360
|
}
|
|
194
361
|
return new Observable((subscriber) => {
|
|
195
|
-
subscriber.error(
|
|
362
|
+
subscriber.error(error);
|
|
196
363
|
subscriber.complete();
|
|
197
364
|
});
|
|
198
365
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
366
|
+
/**
|
|
367
|
+
* 将 Blob 转换为 JSON 对象并抛出错误
|
|
368
|
+
* @param blob Blob 对象
|
|
369
|
+
* @returns Observable<HttpEvent<T>>
|
|
370
|
+
*/
|
|
371
|
+
convertBlobToJson(blob) {
|
|
372
|
+
return new Observable((subscriber) => {
|
|
373
|
+
const reader = new FileReader();
|
|
374
|
+
reader.addEventListener('loadend', () => {
|
|
375
|
+
try {
|
|
376
|
+
const json = JSON.parse(reader.result);
|
|
377
|
+
subscriber.error(json);
|
|
378
|
+
}
|
|
379
|
+
catch (parseError) {
|
|
380
|
+
subscriber.error(parseError);
|
|
381
|
+
}
|
|
382
|
+
finally {
|
|
383
|
+
subscriber.complete();
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
reader.addEventListener('error', () => {
|
|
387
|
+
subscriber.error(new Error('读取 Blob 数据失败'));
|
|
210
388
|
subscriber.complete();
|
|
211
|
-
}
|
|
389
|
+
});
|
|
390
|
+
reader.readAsText(blob, 'utf-8');
|
|
212
391
|
});
|
|
213
|
-
reader.readAsText(blob, 'utf-8');
|
|
214
392
|
}
|
|
215
393
|
}
|
|
216
394
|
BlobInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: BlobInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -219,8 +397,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImpo
|
|
|
219
397
|
type: Injectable
|
|
220
398
|
}] });
|
|
221
399
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
400
|
+
* 提供 Blob 响应拦截器
|
|
401
|
+
* @returns Provider 配置对象
|
|
402
|
+
* @example
|
|
403
|
+
* providers: [providerDownBlob()]
|
|
224
404
|
*/
|
|
225
405
|
function providerDownBlob() {
|
|
226
406
|
return { provide: HTTP_INTERCEPTORS, useClass: BlobInterceptor, multi: true };
|
|
@@ -230,5 +410,5 @@ function providerDownBlob() {
|
|
|
230
410
|
* Generated bundle index. Do not edit.
|
|
231
411
|
*/
|
|
232
412
|
|
|
233
|
-
export { BlobInterceptor, CacheInterceptor, CustomTokenTemplate, CustomTokenWithHeaderTemplate, ErrorInterceptor, NoAuthTokenTemplate, TokenInterceptor, providerAuthToken, providerDownBlob, providerHttpCache, providerHttpError };
|
|
413
|
+
export { BlobInterceptor, CacheHttpTemplate, CacheInterceptor, CustomTokenTemplate, CustomTokenWithHeaderTemplate, ErrorInterceptor, NoAuthTokenTemplate, TokenInterceptor, providerAuthToken, providerDownBlob, providerHttpCache, providerHttpError };
|
|
234
414
|
//# sourceMappingURL=reskin-core-interceptors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reskin-core-interceptors.js","sources":["../../../library/core/interceptors/token.interceptor.ts","../../../library/core/interceptors/error.interceptor.ts","../../../library/core/interceptors/cache.interceptor.ts","../../../library/core/interceptors/blob.interceptor.ts","../../../library/core/interceptors/reskin-core-interceptors.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS, HttpHeaders } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { RkAuthService } from '@reskin/core/services';\r\nimport { IAuth } from '@reskin/core/entity/user';\r\n\r\n// 定义默认的 token header 名称\r\nconst DEFAULT_TOKEN_HEADER_NAME = 'Authorization';\r\nconst TOKEN_CONTROL_HEADER = 'Token-Control';\r\nconst CUSTOM_TOKEN_HEADER = 'Custom-Token';\r\nconst CUSTOM_TOKEN_HEADER_NAME = 'Custom-Token-Header';\r\nconst AUTH_ID_HEADER = 'X-Auth-Id';\r\n\r\n@Injectable()\r\nexport class TokenInterceptor implements HttpInterceptor {\r\n constructor(private service: RkAuthService) {}\r\n\r\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\r\n const tc = request.headers.get(TOKEN_CONTROL_HEADER);\r\n // 检查是否提供了自定义token\r\n const customToken = request.headers.get(CUSTOM_TOKEN_HEADER);\r\n // 检查是否提供了自定义token header名称\r\n const customTokenHeaderName = request.headers.get(CUSTOM_TOKEN_HEADER_NAME) || DEFAULT_TOKEN_HEADER_NAME;\r\n\r\n if (tc !== 'no-token') {\r\n let headers: { [name: string]: string | string[] } = {};\r\n\r\n if (customToken) {\r\n // 使用自定义token\r\n headers[customTokenHeaderName] = customToken;\r\n } else {\r\n // 使用默认认证信息\r\n const auth: IAuth = this.service.token;\r\n if (auth.token) {\r\n headers[DEFAULT_TOKEN_HEADER_NAME] = auth.token;\r\n headers[AUTH_ID_HEADER] = auth.id;\r\n }\r\n }\r\n\r\n if (Object.keys(headers).length > 0) {\r\n request = request.clone({ setHeaders: headers });\r\n }\r\n }\r\n return next.handle(request);\r\n }\r\n}\r\n\r\n/**\r\n * 请求头增加token验证拦截器\r\n */\r\nexport function providerAuthToken() {\r\n return { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true };\r\n}\r\n\r\n/**\r\n * 不带token验证信息请求\r\n * @param urls 地址\r\n * @param params 参数\r\n * @constructor\r\n */\r\nexport function NoAuthTokenTemplate(urls: TemplateStringsArray, ...params: any[]): [string, { headers: HttpHeaders }] {\r\n let [url] = urls;\r\n if (params.length > 0) {\r\n url = String.raw(urls, ...params);\r\n }\r\n return [url, { headers: new HttpHeaders({ 'Token-Control': 'no-token' }) }];\r\n}\r\n\r\n/**\r\n * 使用自定义token的请求\r\n * @param token 自定义token值\r\n * @param urls 地址\r\n * @param params 参数\r\n * @constructor\r\n */\r\nexport function CustomTokenTemplate(token: string, urls: TemplateStringsArray, ...params: any[]): [string, { headers: HttpHeaders }] {\r\n let [url] = urls;\r\n if (params.length > 0) {\r\n url = String.raw(urls, ...params);\r\n }\r\n return [url, { headers: new HttpHeaders({ 'Custom-Token': token }) }];\r\n}\r\n\r\n/**\r\n * 使用自定义token和自定义header名称的请求\r\n * @param token 自定义token值\r\n * @param headerName 自定义header名称\r\n * @param urls 地址\r\n * @param params 参数\r\n * @constructor\r\n */\r\nexport function CustomTokenWithHeaderTemplate(\r\n token: string,\r\n headerName: string,\r\n urls: TemplateStringsArray,\r\n ...params: any[]\r\n): [string, { headers: HttpHeaders }] {\r\n let [url] = urls;\r\n if (params.length > 0) {\r\n url = String.raw(urls, ...params);\r\n }\r\n return [\r\n url,\r\n {\r\n headers: new HttpHeaders({\r\n 'Custom-Token': token,\r\n 'Custom-Token-Header': headerName,\r\n }),\r\n },\r\n ];\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS } from '@angular/common/http';\r\nimport { Observable, of } from 'rxjs';\r\nimport { catchError } from 'rxjs/operators';\r\nimport { Router } from '@angular/router';\r\n\r\n@Injectable()\r\nexport class ErrorInterceptor implements HttpInterceptor {\r\n constructor(private router: Router) {}\r\n\r\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\r\n return next.handle(request).pipe(\r\n catchError((result) => {\r\n if (result.status === 401) {\r\n this.router.navigate(['/errors/401']).then();\r\n }\r\n if (result.error.code) {\r\n return of(result.error);\r\n }\r\n throw result.error.msg ?? result.message;\r\n }),\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * 请求错误拦截器\r\n */\r\nexport function providerHttpError() {\r\n return { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true };\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { shareReplay } from 'rxjs/operators';\r\nimport { RkCacheHttpService } from '@reskin/core/services';\r\n\r\n@Injectable()\r\nexport class CacheInterceptor implements HttpInterceptor {\r\n constructor(private cacheHttp: RkCacheHttpService) {}\r\n\r\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\r\n // 1.判断是GET\r\n // 2.header中添加 Cache-Map: Storage\r\n const cacheMap = request.headers.get('Cache-Map');\r\n if (request.method === 'GET' && cacheMap === 'Storage') {\r\n let response = this.cacheHttp.get(request.url);\r\n if (!response) {\r\n response = next.handle(request).pipe(shareReplay(1));\r\n this.cacheHttp.set(request.url, response);\r\n }\r\n return response;\r\n }\r\n return next.handle(request);\r\n }\r\n}\r\n\r\n/**\r\n * GET请求缓存拦截器\r\n */\r\nexport function providerHttpCache() {\r\n return { provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true };\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport {\r\n HttpRequest,\r\n HttpHandler,\r\n HttpEvent,\r\n HttpInterceptor,\r\n HttpEventType,\r\n HttpResponse,\r\n HttpErrorResponse,\r\n HTTP_INTERCEPTORS,\r\n} from '@angular/common/http';\r\nimport { Observable, Subscriber } from 'rxjs';\r\nimport { catchError, switchMap } from 'rxjs/operators';\r\n\r\n@Injectable()\r\nexport class BlobInterceptor implements HttpInterceptor {\r\n intercept<T>(request: HttpRequest<T>, next: HttpHandler): Observable<HttpEvent<T>> {\r\n if (request.responseType !== 'blob') {\r\n return next.handle(request);\r\n }\r\n return next.handle(request).pipe(\r\n switchMap((response: HttpEvent<any>) => this.handleBlobResponse(response)),\r\n catchError((response: HttpErrorResponse) => this.handleBlobError(response)),\r\n );\r\n }\r\n\r\n private handleBlobResponse<T>(response: HttpEvent<any>): Observable<HttpEvent<any>> {\r\n if (response.type !== HttpEventType.Response) {\r\n return new Observable((subscriber) => {\r\n subscriber.next(response);\r\n subscriber.complete();\r\n });\r\n }\r\n\r\n if (response instanceof HttpResponse && response.body && response.body.type === 'application/json') {\r\n return new Observable((subscriber) => this.blobToJson<T>(response.body, subscriber));\r\n }\r\n\r\n return new Observable((subscriber) => {\r\n subscriber.next(response);\r\n subscriber.complete();\r\n });\r\n }\r\n\r\n private handleBlobError<T>(response: HttpErrorResponse): Observable<HttpEvent<any>> {\r\n if (response.error && response.error.type === 'application/json') {\r\n return new Observable((subscriber) => this.blobToJson<T>(response.error, subscriber));\r\n }\r\n\r\n return new Observable((subscriber) => {\r\n subscriber.error(response);\r\n subscriber.complete();\r\n });\r\n }\r\n\r\n private blobToJson<T>(blob: Blob, subscriber: Subscriber<HttpEvent<T>>) {\r\n const reader = new FileReader();\r\n reader.addEventListener('loadend', () => {\r\n try {\r\n const json: T = JSON.parse(reader.result as string);\r\n subscriber.error(json);\r\n } catch (error) {\r\n subscriber.error(error);\r\n } finally {\r\n subscriber.complete();\r\n }\r\n });\r\n reader.readAsText(blob, 'utf-8');\r\n }\r\n}\r\n\r\n/**\r\n * 下载文件拦截器\r\n * blob类型的请求会被处理\r\n */\r\nexport function providerDownBlob() {\r\n return { provide: HTTP_INTERCEPTORS, useClass: BlobInterceptor, multi: true };\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reskin-core-interceptors.js","sources":["../../../library/core/interceptors/types.ts","../../../library/core/interceptors/token.interceptor.ts","../../../library/core/interceptors/error.interceptor.ts","../../../library/core/interceptors/cache.interceptor.ts","../../../library/core/interceptors/blob.interceptor.ts","../../../library/core/interceptors/reskin-core-interceptors.ts"],"sourcesContent":["/**\r\n * HTTP 拦截器相关类型定义\r\n */\r\n\r\n/**\r\n * Token 拦截器配置\r\n */\r\nexport interface TokenInterceptorConfig {\r\n /**\r\n * 默认的 Token Header 名称\r\n * @default 'Authorization'\r\n */\r\n tokenHeaderName?: string;\r\n /**\r\n * 认证 ID Header 名称\r\n * @default 'X-Auth-Id'\r\n */\r\n authIdHeaderName?: string;\r\n}\r\n\r\n/**\r\n * 错误拦截器配置\r\n */\r\nexport interface ErrorInterceptorConfig {\r\n /**\r\n * 401 错误跳转路径\r\n * @default '/errors/401'\r\n */\r\n unauthorizedPath?: string;\r\n /**\r\n * 是否启用错误日志\r\n * @default false\r\n */\r\n enableLogging?: boolean;\r\n /**\r\n * 自定义错误处理函数\r\n */\r\n customErrorHandler?: (error: any) => void;\r\n}\r\n\r\n/**\r\n * 缓存拦截器配置\r\n */\r\nexport interface CacheInterceptorConfig {\r\n /**\r\n * 缓存最大数量\r\n * @default 100\r\n */\r\n maxCacheSize?: number;\r\n /**\r\n * 缓存过期时间(毫秒)\r\n * @default undefined (永不过期)\r\n */\r\n cacheExpiration?: number;\r\n}\r\n\r\n/**\r\n * HTTP 请求选项扩展\r\n */\r\nexport interface HttpRequestOptions {\r\n headers?: { [name: string]: string | string[] };\r\n}\r\n\r\n/**\r\n * Token 控制类型\r\n */\r\nexport type TokenControl = 'no-token' | 'custom-token';\r\n\r\n/**\r\n * 缓存策略类型\r\n */\r\nexport type CacheStrategy = 'Storage' | 'Memory';\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS, HttpHeaders } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { RkAuthService } from '@reskin/core/services';\r\nimport { IAuth } from '@reskin/core/entity/user';\r\n\r\n/**\r\n * Token 拦截器常量\r\n */\r\nconst DEFAULT_TOKEN_HEADER_NAME = 'Authorization';\r\nconst TOKEN_CONTROL_HEADER = 'Token-Control';\r\nconst CUSTOM_TOKEN_HEADER = 'Custom-Token';\r\nconst CUSTOM_TOKEN_HEADER_NAME = 'Custom-Token-Header';\r\nconst AUTH_ID_HEADER = 'X-Auth-Id';\r\n\r\n/**\r\n * Token 拦截器\r\n * 自动为 HTTP 请求添加认证 Token\r\n */\r\n@Injectable()\r\nexport class TokenInterceptor implements HttpInterceptor {\r\n constructor(private authService: RkAuthService) {}\r\n\r\n /**\r\n * 拦截 HTTP 请求,添加 Token 认证信息\r\n * @param request HTTP 请求对象\r\n * @param next 下一个拦截器处理器\r\n * @returns Observable<HttpEvent<unknown>>\r\n */\r\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\r\n const tokenControl = request.headers.get(TOKEN_CONTROL_HEADER);\r\n \r\n // 如果明确指定不需要 Token,直接放行\r\n if (tokenControl === 'no-token') {\r\n return next.handle(request);\r\n }\r\n\r\n const customToken = request.headers.get(CUSTOM_TOKEN_HEADER);\r\n const customTokenHeaderName = request.headers.get(CUSTOM_TOKEN_HEADER_NAME) || DEFAULT_TOKEN_HEADER_NAME;\r\n\r\n const headers: { [name: string]: string | string[] } = {};\r\n\r\n if (customToken) {\r\n // 使用自定义 Token\r\n headers[customTokenHeaderName] = customToken;\r\n } else {\r\n // 使用默认认证信息\r\n const auth: IAuth = this.authService.token;\r\n if (auth?.token) {\r\n headers[DEFAULT_TOKEN_HEADER_NAME] = auth.token;\r\n if (auth.id) {\r\n headers[AUTH_ID_HEADER] = auth.id;\r\n }\r\n }\r\n }\r\n\r\n // 如果有需要添加的 Header,克隆请求并添加\r\n if (Object.keys(headers).length > 0) {\r\n request = request.clone({ setHeaders: headers });\r\n }\r\n\r\n return next.handle(request);\r\n }\r\n}\r\n\r\n/**\r\n * 提供 Token 拦截器\r\n * @returns Provider 配置对象\r\n */\r\nexport function providerAuthToken() {\r\n return { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true };\r\n}\r\n\r\n/**\r\n * 创建不带 Token 的请求配置\r\n * @param urls 模板字符串数组\r\n * @param params 模板参数\r\n * @returns [url, options] 元组\r\n * @example\r\n * this.http.get(...NoAuthTokenTemplate`/api/public/data`).subscribe();\r\n */\r\nexport function NoAuthTokenTemplate(urls: TemplateStringsArray, ...params: any[]): [string, { headers: HttpHeaders }] {\r\n const url = params.length > 0 ? String.raw(urls, ...params) : urls[0];\r\n return [url, { headers: new HttpHeaders({ [TOKEN_CONTROL_HEADER]: 'no-token' }) }];\r\n}\r\n\r\n/**\r\n * 创建使用自定义 Token 的请求配置\r\n * @param token 自定义 Token 值\r\n * @param urls 模板字符串数组\r\n * @param params 模板参数\r\n * @returns [url, options] 元组\r\n * @example\r\n * this.http.get(...CustomTokenTemplate('my-token', `/api/data`)).subscribe();\r\n */\r\nexport function CustomTokenTemplate(token: string, urls: TemplateStringsArray, ...params: any[]): [string, { headers: HttpHeaders }] {\r\n const url = params.length > 0 ? String.raw(urls, ...params) : urls[0];\r\n return [url, { headers: new HttpHeaders({ [CUSTOM_TOKEN_HEADER]: token }) }];\r\n}\r\n\r\n/**\r\n * 创建使用自定义 Token 和自定义 Header 名称的请求配置\r\n * @param token 自定义 Token 值\r\n * @param headerName 自定义 Header 名称\r\n * @param urls 模板字符串数组\r\n * @param params 模板参数\r\n * @returns [url, options] 元组\r\n * @example\r\n * this.http.get(...CustomTokenWithHeaderTemplate('my-token', 'X-API-Key', `/api/data`)).subscribe();\r\n */\r\nexport function CustomTokenWithHeaderTemplate(\r\n token: string,\r\n headerName: string,\r\n urls: TemplateStringsArray,\r\n ...params: any[]\r\n): [string, { headers: HttpHeaders }] {\r\n const url = params.length > 0 ? String.raw(urls, ...params) : urls[0];\r\n return [\r\n url,\r\n {\r\n headers: new HttpHeaders({\r\n [CUSTOM_TOKEN_HEADER]: token,\r\n [CUSTOM_TOKEN_HEADER_NAME]: headerName,\r\n }),\r\n },\r\n ];\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS, HttpErrorResponse } from '@angular/common/http';\r\nimport { Observable, throwError } from 'rxjs';\r\nimport { catchError } from 'rxjs/operators';\r\nimport { Router } from '@angular/router';\r\nimport { ErrorInterceptorConfig } from './types';\r\n\r\n/**\r\n * 默认配置\r\n */\r\nconst DEFAULT_CONFIG: ErrorInterceptorConfig = {\r\n unauthorizedPath: '/errors/401',\r\n enableLogging: false,\r\n};\r\n\r\n/**\r\n * HTTP 错误拦截器\r\n * 统一处理 HTTP 请求错误,包括 401 未授权错误的自动跳转\r\n */\r\n@Injectable()\r\nexport class ErrorInterceptor implements HttpInterceptor {\r\n private config: ErrorInterceptorConfig = DEFAULT_CONFIG;\r\n\r\n constructor(private router: Router) {}\r\n\r\n /**\r\n * 设置拦截器配置\r\n * @param config 配置对象\r\n */\r\n setConfig(config: ErrorInterceptorConfig): void {\r\n this.config = { ...DEFAULT_CONFIG, ...config };\r\n }\r\n\r\n /**\r\n * 拦截 HTTP 请求,处理错误响应\r\n * @param request HTTP 请求对象\r\n * @param next 下一个拦截器处理器\r\n * @returns Observable<HttpEvent<unknown>>\r\n */\r\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\r\n return next.handle(request).pipe(\r\n catchError((error: HttpErrorResponse) => {\r\n // 处理 401 未授权错误\r\n if (error.status === 401) {\r\n this.handleUnauthorizedError();\r\n return throwError(error);\r\n }\r\n\r\n // 记录错误日志\r\n if (this.config.enableLogging) {\r\n console.error('[HTTP Error]', {\r\n url: request.url,\r\n method: request.method,\r\n status: error.status,\r\n message: error.message,\r\n error: error.error,\r\n });\r\n }\r\n\r\n // 提取错误信息\r\n const errorMessage = this.extractErrorMessage(error);\r\n return throwError(new Error(errorMessage));\r\n }),\r\n );\r\n }\r\n\r\n /**\r\n * 处理 401 未授权错误\r\n */\r\n private handleUnauthorizedError(): void {\r\n const path = this.config.unauthorizedPath || DEFAULT_CONFIG.unauthorizedPath;\r\n this.router.navigate([path]).catch((err) => {\r\n console.error('导航到错误页面失败:', err);\r\n });\r\n }\r\n\r\n /**\r\n * 提取错误信息\r\n * @param error HTTP 错误响应\r\n * @returns 错误信息字符串\r\n */\r\n private extractErrorMessage(error: HttpErrorResponse): string {\r\n if (error.error) {\r\n // 尝试从 error.error 中提取信息\r\n if (typeof error.error === 'string') {\r\n return error.error;\r\n }\r\n if (error.error.msg) {\r\n return error.error.msg;\r\n }\r\n if (error.error.message) {\r\n return error.error.message;\r\n }\r\n }\r\n // 使用默认错误信息\r\n return error.message || `HTTP Error ${error.status}`;\r\n }\r\n}\r\n\r\n/**\r\n * 提供 HTTP 错误拦截器\r\n * @param config 可选的配置对象\r\n * @returns Provider 配置对象\r\n * @example\r\n * providers: [\r\n * providerHttpError({ unauthorizedPath: '/login', enableLogging: true })\r\n * ]\r\n */\r\nexport function providerHttpError(config?: ErrorInterceptorConfig) {\r\n if (config) {\r\n // 如果有配置,使用 useFactory\r\n return {\r\n provide: HTTP_INTERCEPTORS,\r\n useFactory: (router: Router) => {\r\n const interceptor = new ErrorInterceptor(router);\r\n interceptor.setConfig(config);\r\n return interceptor;\r\n },\r\n deps: [Router],\r\n multi: true,\r\n };\r\n } else {\r\n // 没有配置,直接使用 useClass\r\n return {\r\n provide: HTTP_INTERCEPTORS,\r\n useClass: ErrorInterceptor,\r\n multi: true,\r\n };\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HTTP_INTERCEPTORS, HttpHeaders } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { shareReplay } from 'rxjs/operators';\r\nimport { RkCacheHttpService } from '@reskin/core/services';\r\n\r\n/**\r\n * 缓存策略标识\r\n */\r\nconst CACHE_HEADER = 'Cache-Map';\r\nconst CACHE_STRATEGY = 'Storage';\r\n\r\n/**\r\n * HTTP 缓存拦截器\r\n * 为 GET 请求提供缓存功能,减少重复请求\r\n */\r\n@Injectable()\r\nexport class CacheInterceptor implements HttpInterceptor {\r\n constructor(private cacheHttpService: RkCacheHttpService) {}\r\n\r\n /**\r\n * 拦截 HTTP 请求,实现缓存逻辑\r\n * @param request HTTP 请求对象\r\n * @param next 下一个拦截器处理器\r\n * @returns Observable<HttpEvent<unknown>>\r\n */\r\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\r\n // 只缓存 GET 请求且明确标记了缓存策略的请求\r\n const cacheStrategy = request.headers.get(CACHE_HEADER);\r\n \r\n if (request.method === 'GET' && cacheStrategy === CACHE_STRATEGY) {\r\n // 尝试从缓存中获取响应\r\n let cachedResponse = this.cacheHttpService.get(request.url);\r\n \r\n if (!cachedResponse) {\r\n // 缓存未命中,发起请求并缓存结果\r\n cachedResponse = next.handle(request).pipe(shareReplay(1));\r\n this.cacheHttpService.set(request.url, cachedResponse);\r\n }\r\n \r\n return cachedResponse;\r\n }\r\n\r\n // 非缓存请求,直接放行\r\n return next.handle(request);\r\n }\r\n}\r\n\r\n/**\r\n * 提供 HTTP 缓存拦截器\r\n * @returns Provider 配置对象\r\n * @example\r\n * providers: [providerHttpCache()]\r\n */\r\nexport function providerHttpCache() {\r\n return { provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true };\r\n}\r\n\r\n/**\r\n * 创建带缓存标记的 GET 请求配置\r\n * @param urls 模板字符串数组\r\n * @param params 模板参数\r\n * @returns [url, options] 元组\r\n * @example\r\n * this.http.get(...CacheHttpTemplate`/api/data`).subscribe();\r\n */\r\nexport function CacheHttpTemplate(urls: TemplateStringsArray, ...params: any[]): [string, { headers: HttpHeaders }] {\r\n const url = params.length > 0 ? String.raw(urls, ...params) : urls[0];\r\n return [url, { headers: new HttpHeaders({ [CACHE_HEADER]: CACHE_STRATEGY }) }];\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport {\r\n HttpRequest,\r\n HttpHandler,\r\n HttpEvent,\r\n HttpInterceptor,\r\n HttpEventType,\r\n HttpResponse,\r\n HttpErrorResponse,\r\n HTTP_INTERCEPTORS,\r\n} from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { switchMap, catchError } from 'rxjs/operators';\r\n\r\n/**\r\n * Blob 响应拦截器\r\n * 处理文件下载请求中的 JSON 错误响应\r\n */\r\n@Injectable()\r\nexport class BlobInterceptor implements HttpInterceptor {\r\n /**\r\n * 拦截 HTTP 请求,处理 Blob 类型响应\r\n * @param request HTTP 请求对象\r\n * @param next 下一个拦截器处理器\r\n * @returns Observable<HttpEvent<T>>\r\n */\r\n intercept<T>(request: HttpRequest<T>, next: HttpHandler): Observable<HttpEvent<T>> {\r\n // 只处理 responseType 为 blob 的请求\r\n if (request.responseType !== 'blob') {\r\n return next.handle(request);\r\n }\r\n\r\n return next.handle(request).pipe(\r\n switchMap((event: HttpEvent<any>) => this.handleBlobResponse(event)),\r\n catchError((error: HttpErrorResponse) => this.handleBlobError(error)),\r\n );\r\n }\r\n\r\n /**\r\n * 处理 Blob 响应事件\r\n * @param event HTTP 事件\r\n * @returns Observable<HttpEvent<any>>\r\n */\r\n private handleBlobResponse(event: HttpEvent<any>): Observable<HttpEvent<any>> {\r\n // 只处理完整的响应事件\r\n if (event.type !== HttpEventType.Response) {\r\n return new Observable((subscriber) => {\r\n subscriber.next(event);\r\n subscriber.complete();\r\n });\r\n }\r\n\r\n // 检查响应体是否为 JSON 类型(通常表示错误)\r\n if (event instanceof HttpResponse && event.body?.type === 'application/json') {\r\n return this.convertBlobToJson(event.body);\r\n }\r\n\r\n return new Observable((subscriber) => {\r\n subscriber.next(event);\r\n subscriber.complete();\r\n });\r\n }\r\n\r\n /**\r\n * 处理 Blob 错误响应\r\n * @param error HTTP 错误响应\r\n * @returns Observable<HttpEvent<any>>\r\n */\r\n private handleBlobError(error: HttpErrorResponse): Observable<HttpEvent<any>> {\r\n // 如果错误响应体是 JSON 类型的 Blob,转换为 JSON 对象\r\n if (error.error?.type === 'application/json') {\r\n return this.convertBlobToJson(error.error);\r\n }\r\n\r\n return new Observable((subscriber) => {\r\n subscriber.error(error);\r\n subscriber.complete();\r\n });\r\n }\r\n\r\n /**\r\n * 将 Blob 转换为 JSON 对象并抛出错误\r\n * @param blob Blob 对象\r\n * @returns Observable<HttpEvent<T>>\r\n */\r\n private convertBlobToJson<T>(blob: Blob): Observable<HttpEvent<T>> {\r\n return new Observable((subscriber) => {\r\n const reader = new FileReader();\r\n \r\n reader.addEventListener('loadend', () => {\r\n try {\r\n const json: T = JSON.parse(reader.result as string);\r\n subscriber.error(json);\r\n } catch (parseError) {\r\n subscriber.error(parseError);\r\n } finally {\r\n subscriber.complete();\r\n }\r\n });\r\n\r\n reader.addEventListener('error', () => {\r\n subscriber.error(new Error('读取 Blob 数据失败'));\r\n subscriber.complete();\r\n });\r\n\r\n reader.readAsText(blob, 'utf-8');\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * 提供 Blob 响应拦截器\r\n * @returns Provider 配置对象\r\n * @example\r\n * providers: [providerDownBlob()]\r\n */\r\nexport function providerDownBlob() {\r\n return { provide: HTTP_INTERCEPTORS, useClass: BlobInterceptor, multi: true };\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1"],"mappings":"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"}
|