@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
|
@@ -503,39 +503,54 @@
|
|
|
503
503
|
__disposeResources: __disposeResources,
|
|
504
504
|
};
|
|
505
505
|
|
|
506
|
-
|
|
506
|
+
/**
|
|
507
|
+
* Token 拦截器常量
|
|
508
|
+
*/
|
|
507
509
|
var DEFAULT_TOKEN_HEADER_NAME = 'Authorization';
|
|
508
510
|
var TOKEN_CONTROL_HEADER = 'Token-Control';
|
|
509
511
|
var CUSTOM_TOKEN_HEADER = 'Custom-Token';
|
|
510
512
|
var CUSTOM_TOKEN_HEADER_NAME = 'Custom-Token-Header';
|
|
511
513
|
var AUTH_ID_HEADER = 'X-Auth-Id';
|
|
514
|
+
/**
|
|
515
|
+
* Token 拦截器
|
|
516
|
+
* 自动为 HTTP 请求添加认证 Token
|
|
517
|
+
*/
|
|
512
518
|
var TokenInterceptor = /** @class */ (function () {
|
|
513
|
-
function TokenInterceptor(
|
|
514
|
-
this.
|
|
519
|
+
function TokenInterceptor(authService) {
|
|
520
|
+
this.authService = authService;
|
|
515
521
|
}
|
|
522
|
+
/**
|
|
523
|
+
* 拦截 HTTP 请求,添加 Token 认证信息
|
|
524
|
+
* @param request HTTP 请求对象
|
|
525
|
+
* @param next 下一个拦截器处理器
|
|
526
|
+
* @returns Observable<HttpEvent<unknown>>
|
|
527
|
+
*/
|
|
516
528
|
TokenInterceptor.prototype.intercept = function (request, next) {
|
|
517
|
-
var
|
|
518
|
-
//
|
|
529
|
+
var tokenControl = request.headers.get(TOKEN_CONTROL_HEADER);
|
|
530
|
+
// 如果明确指定不需要 Token,直接放行
|
|
531
|
+
if (tokenControl === 'no-token') {
|
|
532
|
+
return next.handle(request);
|
|
533
|
+
}
|
|
519
534
|
var customToken = request.headers.get(CUSTOM_TOKEN_HEADER);
|
|
520
|
-
// 检查是否提供了自定义token header名称
|
|
521
535
|
var customTokenHeaderName = request.headers.get(CUSTOM_TOKEN_HEADER_NAME) || DEFAULT_TOKEN_HEADER_NAME;
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
536
|
+
var headers = {};
|
|
537
|
+
if (customToken) {
|
|
538
|
+
// 使用自定义 Token
|
|
539
|
+
headers[customTokenHeaderName] = customToken;
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
// 使用默认认证信息
|
|
543
|
+
var auth = this.authService.token;
|
|
544
|
+
if (auth === null || auth === void 0 ? void 0 : auth.token) {
|
|
545
|
+
headers[DEFAULT_TOKEN_HEADER_NAME] = auth.token;
|
|
546
|
+
if (auth.id) {
|
|
533
547
|
headers[AUTH_ID_HEADER] = auth.id;
|
|
534
548
|
}
|
|
535
549
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
550
|
+
}
|
|
551
|
+
// 如果有需要添加的 Header,克隆请求并添加
|
|
552
|
+
if (Object.keys(headers).length > 0) {
|
|
553
|
+
request = request.clone({ setHeaders: headers });
|
|
539
554
|
}
|
|
540
555
|
return next.handle(request);
|
|
541
556
|
};
|
|
@@ -547,91 +562,157 @@
|
|
|
547
562
|
type: i0.Injectable
|
|
548
563
|
}], ctorParameters: function () { return [{ type: i1__namespace.RkAuthService }]; } });
|
|
549
564
|
/**
|
|
550
|
-
*
|
|
565
|
+
* 提供 Token 拦截器
|
|
566
|
+
* @returns Provider 配置对象
|
|
551
567
|
*/
|
|
552
568
|
function providerAuthToken() {
|
|
553
569
|
return { provide: http.HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true };
|
|
554
570
|
}
|
|
555
571
|
/**
|
|
556
|
-
*
|
|
557
|
-
* @param urls
|
|
558
|
-
* @param params
|
|
559
|
-
* @
|
|
572
|
+
* 创建不带 Token 的请求配置
|
|
573
|
+
* @param urls 模板字符串数组
|
|
574
|
+
* @param params 模板参数
|
|
575
|
+
* @returns [url, options] 元组
|
|
576
|
+
* @example
|
|
577
|
+
* this.http.get(...NoAuthTokenTemplate`/api/public/data`).subscribe();
|
|
560
578
|
*/
|
|
561
579
|
function NoAuthTokenTemplate(urls) {
|
|
580
|
+
var _a;
|
|
562
581
|
var params = [];
|
|
563
582
|
for (var _i = 1; _i < arguments.length; _i++) {
|
|
564
583
|
params[_i - 1] = arguments[_i];
|
|
565
584
|
}
|
|
566
|
-
var
|
|
567
|
-
|
|
568
|
-
url = String.raw.apply(String, __spreadArray([urls], __read(params)));
|
|
569
|
-
}
|
|
570
|
-
return [url, { headers: new http.HttpHeaders({ 'Token-Control': 'no-token' }) }];
|
|
585
|
+
var url = params.length > 0 ? String.raw.apply(String, __spreadArray([urls], __read(params))) : urls[0];
|
|
586
|
+
return [url, { headers: new http.HttpHeaders((_a = {}, _a[TOKEN_CONTROL_HEADER] = 'no-token', _a)) }];
|
|
571
587
|
}
|
|
572
588
|
/**
|
|
573
|
-
*
|
|
574
|
-
* @param token 自定义
|
|
575
|
-
* @param urls
|
|
576
|
-
* @param params
|
|
577
|
-
* @
|
|
589
|
+
* 创建使用自定义 Token 的请求配置
|
|
590
|
+
* @param token 自定义 Token 值
|
|
591
|
+
* @param urls 模板字符串数组
|
|
592
|
+
* @param params 模板参数
|
|
593
|
+
* @returns [url, options] 元组
|
|
594
|
+
* @example
|
|
595
|
+
* this.http.get(...CustomTokenTemplate('my-token', `/api/data`)).subscribe();
|
|
578
596
|
*/
|
|
579
597
|
function CustomTokenTemplate(token, urls) {
|
|
598
|
+
var _a;
|
|
580
599
|
var params = [];
|
|
581
600
|
for (var _i = 2; _i < arguments.length; _i++) {
|
|
582
601
|
params[_i - 2] = arguments[_i];
|
|
583
602
|
}
|
|
584
|
-
var
|
|
585
|
-
|
|
586
|
-
url = String.raw.apply(String, __spreadArray([urls], __read(params)));
|
|
587
|
-
}
|
|
588
|
-
return [url, { headers: new http.HttpHeaders({ 'Custom-Token': token }) }];
|
|
603
|
+
var url = params.length > 0 ? String.raw.apply(String, __spreadArray([urls], __read(params))) : urls[0];
|
|
604
|
+
return [url, { headers: new http.HttpHeaders((_a = {}, _a[CUSTOM_TOKEN_HEADER] = token, _a)) }];
|
|
589
605
|
}
|
|
590
606
|
/**
|
|
591
|
-
*
|
|
592
|
-
* @param token 自定义
|
|
593
|
-
* @param headerName 自定义
|
|
594
|
-
* @param urls
|
|
595
|
-
* @param params
|
|
596
|
-
* @
|
|
607
|
+
* 创建使用自定义 Token 和自定义 Header 名称的请求配置
|
|
608
|
+
* @param token 自定义 Token 值
|
|
609
|
+
* @param headerName 自定义 Header 名称
|
|
610
|
+
* @param urls 模板字符串数组
|
|
611
|
+
* @param params 模板参数
|
|
612
|
+
* @returns [url, options] 元组
|
|
613
|
+
* @example
|
|
614
|
+
* this.http.get(...CustomTokenWithHeaderTemplate('my-token', 'X-API-Key', `/api/data`)).subscribe();
|
|
597
615
|
*/
|
|
598
616
|
function CustomTokenWithHeaderTemplate(token, headerName, urls) {
|
|
617
|
+
var _a;
|
|
599
618
|
var params = [];
|
|
600
619
|
for (var _i = 3; _i < arguments.length; _i++) {
|
|
601
620
|
params[_i - 3] = arguments[_i];
|
|
602
621
|
}
|
|
603
|
-
var
|
|
604
|
-
if (params.length > 0) {
|
|
605
|
-
url = String.raw.apply(String, __spreadArray([urls], __read(params)));
|
|
606
|
-
}
|
|
622
|
+
var url = params.length > 0 ? String.raw.apply(String, __spreadArray([urls], __read(params))) : urls[0];
|
|
607
623
|
return [
|
|
608
624
|
url,
|
|
609
625
|
{
|
|
610
|
-
headers: new http.HttpHeaders({
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
626
|
+
headers: new http.HttpHeaders((_a = {},
|
|
627
|
+
_a[CUSTOM_TOKEN_HEADER] = token,
|
|
628
|
+
_a[CUSTOM_TOKEN_HEADER_NAME] = headerName,
|
|
629
|
+
_a)),
|
|
614
630
|
},
|
|
615
631
|
];
|
|
616
632
|
}
|
|
617
633
|
|
|
634
|
+
/**
|
|
635
|
+
* 默认配置
|
|
636
|
+
*/
|
|
637
|
+
var DEFAULT_CONFIG = {
|
|
638
|
+
unauthorizedPath: '/errors/401',
|
|
639
|
+
enableLogging: false,
|
|
640
|
+
};
|
|
641
|
+
/**
|
|
642
|
+
* HTTP 错误拦截器
|
|
643
|
+
* 统一处理 HTTP 请求错误,包括 401 未授权错误的自动跳转
|
|
644
|
+
*/
|
|
618
645
|
var ErrorInterceptor = /** @class */ (function () {
|
|
619
646
|
function ErrorInterceptor(router) {
|
|
620
647
|
this.router = router;
|
|
648
|
+
this.config = DEFAULT_CONFIG;
|
|
621
649
|
}
|
|
650
|
+
/**
|
|
651
|
+
* 设置拦截器配置
|
|
652
|
+
* @param config 配置对象
|
|
653
|
+
*/
|
|
654
|
+
ErrorInterceptor.prototype.setConfig = function (config) {
|
|
655
|
+
this.config = Object.assign(Object.assign({}, DEFAULT_CONFIG), config);
|
|
656
|
+
};
|
|
657
|
+
/**
|
|
658
|
+
* 拦截 HTTP 请求,处理错误响应
|
|
659
|
+
* @param request HTTP 请求对象
|
|
660
|
+
* @param next 下一个拦截器处理器
|
|
661
|
+
* @returns Observable<HttpEvent<unknown>>
|
|
662
|
+
*/
|
|
622
663
|
ErrorInterceptor.prototype.intercept = function (request, next) {
|
|
623
664
|
var _this = this;
|
|
624
|
-
return next.handle(request).pipe(operators.catchError(function (
|
|
625
|
-
|
|
626
|
-
if (
|
|
627
|
-
_this.
|
|
665
|
+
return next.handle(request).pipe(operators.catchError(function (error) {
|
|
666
|
+
// 处理 401 未授权错误
|
|
667
|
+
if (error.status === 401) {
|
|
668
|
+
_this.handleUnauthorizedError();
|
|
669
|
+
return rxjs.throwError(error);
|
|
628
670
|
}
|
|
629
|
-
|
|
630
|
-
|
|
671
|
+
// 记录错误日志
|
|
672
|
+
if (_this.config.enableLogging) {
|
|
673
|
+
console.error('[HTTP Error]', {
|
|
674
|
+
url: request.url,
|
|
675
|
+
method: request.method,
|
|
676
|
+
status: error.status,
|
|
677
|
+
message: error.message,
|
|
678
|
+
error: error.error,
|
|
679
|
+
});
|
|
631
680
|
}
|
|
632
|
-
|
|
681
|
+
// 提取错误信息
|
|
682
|
+
var errorMessage = _this.extractErrorMessage(error);
|
|
683
|
+
return rxjs.throwError(new Error(errorMessage));
|
|
633
684
|
}));
|
|
634
685
|
};
|
|
686
|
+
/**
|
|
687
|
+
* 处理 401 未授权错误
|
|
688
|
+
*/
|
|
689
|
+
ErrorInterceptor.prototype.handleUnauthorizedError = function () {
|
|
690
|
+
var path = this.config.unauthorizedPath || DEFAULT_CONFIG.unauthorizedPath;
|
|
691
|
+
this.router.navigate([path]).catch(function (err) {
|
|
692
|
+
console.error('导航到错误页面失败:', err);
|
|
693
|
+
});
|
|
694
|
+
};
|
|
695
|
+
/**
|
|
696
|
+
* 提取错误信息
|
|
697
|
+
* @param error HTTP 错误响应
|
|
698
|
+
* @returns 错误信息字符串
|
|
699
|
+
*/
|
|
700
|
+
ErrorInterceptor.prototype.extractErrorMessage = function (error) {
|
|
701
|
+
if (error.error) {
|
|
702
|
+
// 尝试从 error.error 中提取信息
|
|
703
|
+
if (typeof error.error === 'string') {
|
|
704
|
+
return error.error;
|
|
705
|
+
}
|
|
706
|
+
if (error.error.msg) {
|
|
707
|
+
return error.error.msg;
|
|
708
|
+
}
|
|
709
|
+
if (error.error.message) {
|
|
710
|
+
return error.error.message;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// 使用默认错误信息
|
|
714
|
+
return error.message || "HTTP Error " + error.status;
|
|
715
|
+
};
|
|
635
716
|
return ErrorInterceptor;
|
|
636
717
|
}());
|
|
637
718
|
ErrorInterceptor.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0__namespace, type: ErrorInterceptor, deps: [{ token: i1__namespace$1.Router }], target: i0__namespace.ɵɵFactoryTarget.Injectable });
|
|
@@ -640,28 +721,71 @@
|
|
|
640
721
|
type: i0.Injectable
|
|
641
722
|
}], ctorParameters: function () { return [{ type: i1__namespace$1.Router }]; } });
|
|
642
723
|
/**
|
|
643
|
-
*
|
|
724
|
+
* 提供 HTTP 错误拦截器
|
|
725
|
+
* @param config 可选的配置对象
|
|
726
|
+
* @returns Provider 配置对象
|
|
727
|
+
* @example
|
|
728
|
+
* providers: [
|
|
729
|
+
* providerHttpError({ unauthorizedPath: '/login', enableLogging: true })
|
|
730
|
+
* ]
|
|
644
731
|
*/
|
|
645
|
-
function providerHttpError() {
|
|
646
|
-
|
|
732
|
+
function providerHttpError(config) {
|
|
733
|
+
if (config) {
|
|
734
|
+
// 如果有配置,使用 useFactory
|
|
735
|
+
return {
|
|
736
|
+
provide: http.HTTP_INTERCEPTORS,
|
|
737
|
+
useFactory: function (router) {
|
|
738
|
+
var interceptor = new ErrorInterceptor(router);
|
|
739
|
+
interceptor.setConfig(config);
|
|
740
|
+
return interceptor;
|
|
741
|
+
},
|
|
742
|
+
deps: [i1$1.Router],
|
|
743
|
+
multi: true,
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
// 没有配置,直接使用 useClass
|
|
748
|
+
return {
|
|
749
|
+
provide: http.HTTP_INTERCEPTORS,
|
|
750
|
+
useClass: ErrorInterceptor,
|
|
751
|
+
multi: true,
|
|
752
|
+
};
|
|
753
|
+
}
|
|
647
754
|
}
|
|
648
755
|
|
|
756
|
+
/**
|
|
757
|
+
* 缓存策略标识
|
|
758
|
+
*/
|
|
759
|
+
var CACHE_HEADER = 'Cache-Map';
|
|
760
|
+
var CACHE_STRATEGY = 'Storage';
|
|
761
|
+
/**
|
|
762
|
+
* HTTP 缓存拦截器
|
|
763
|
+
* 为 GET 请求提供缓存功能,减少重复请求
|
|
764
|
+
*/
|
|
649
765
|
var CacheInterceptor = /** @class */ (function () {
|
|
650
|
-
function CacheInterceptor(
|
|
651
|
-
this.
|
|
766
|
+
function CacheInterceptor(cacheHttpService) {
|
|
767
|
+
this.cacheHttpService = cacheHttpService;
|
|
652
768
|
}
|
|
769
|
+
/**
|
|
770
|
+
* 拦截 HTTP 请求,实现缓存逻辑
|
|
771
|
+
* @param request HTTP 请求对象
|
|
772
|
+
* @param next 下一个拦截器处理器
|
|
773
|
+
* @returns Observable<HttpEvent<unknown>>
|
|
774
|
+
*/
|
|
653
775
|
CacheInterceptor.prototype.intercept = function (request, next) {
|
|
654
|
-
//
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
var
|
|
659
|
-
if (!
|
|
660
|
-
|
|
661
|
-
|
|
776
|
+
// 只缓存 GET 请求且明确标记了缓存策略的请求
|
|
777
|
+
var cacheStrategy = request.headers.get(CACHE_HEADER);
|
|
778
|
+
if (request.method === 'GET' && cacheStrategy === CACHE_STRATEGY) {
|
|
779
|
+
// 尝试从缓存中获取响应
|
|
780
|
+
var cachedResponse = this.cacheHttpService.get(request.url);
|
|
781
|
+
if (!cachedResponse) {
|
|
782
|
+
// 缓存未命中,发起请求并缓存结果
|
|
783
|
+
cachedResponse = next.handle(request).pipe(operators.shareReplay(1));
|
|
784
|
+
this.cacheHttpService.set(request.url, cachedResponse);
|
|
662
785
|
}
|
|
663
|
-
return
|
|
786
|
+
return cachedResponse;
|
|
664
787
|
}
|
|
788
|
+
// 非缓存请求,直接放行
|
|
665
789
|
return next.handle(request);
|
|
666
790
|
};
|
|
667
791
|
return CacheInterceptor;
|
|
@@ -672,63 +796,118 @@
|
|
|
672
796
|
type: i0.Injectable
|
|
673
797
|
}], ctorParameters: function () { return [{ type: i1__namespace.RkCacheHttpService }]; } });
|
|
674
798
|
/**
|
|
675
|
-
*
|
|
799
|
+
* 提供 HTTP 缓存拦截器
|
|
800
|
+
* @returns Provider 配置对象
|
|
801
|
+
* @example
|
|
802
|
+
* providers: [providerHttpCache()]
|
|
676
803
|
*/
|
|
677
804
|
function providerHttpCache() {
|
|
678
805
|
return { provide: http.HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true };
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* 创建带缓存标记的 GET 请求配置
|
|
809
|
+
* @param urls 模板字符串数组
|
|
810
|
+
* @param params 模板参数
|
|
811
|
+
* @returns [url, options] 元组
|
|
812
|
+
* @example
|
|
813
|
+
* this.http.get(...CacheHttpTemplate`/api/data`).subscribe();
|
|
814
|
+
*/
|
|
815
|
+
function CacheHttpTemplate(urls) {
|
|
816
|
+
var _a;
|
|
817
|
+
var params = [];
|
|
818
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
819
|
+
params[_i - 1] = arguments[_i];
|
|
820
|
+
}
|
|
821
|
+
var url = params.length > 0 ? String.raw.apply(String, __spreadArray([urls], __read(params))) : urls[0];
|
|
822
|
+
return [url, { headers: new http.HttpHeaders((_a = {}, _a[CACHE_HEADER] = CACHE_STRATEGY, _a)) }];
|
|
679
823
|
}
|
|
680
824
|
|
|
825
|
+
/**
|
|
826
|
+
* Blob 响应拦截器
|
|
827
|
+
* 处理文件下载请求中的 JSON 错误响应
|
|
828
|
+
*/
|
|
681
829
|
var BlobInterceptor = /** @class */ (function () {
|
|
682
830
|
function BlobInterceptor() {
|
|
683
831
|
}
|
|
832
|
+
/**
|
|
833
|
+
* 拦截 HTTP 请求,处理 Blob 类型响应
|
|
834
|
+
* @param request HTTP 请求对象
|
|
835
|
+
* @param next 下一个拦截器处理器
|
|
836
|
+
* @returns Observable<HttpEvent<T>>
|
|
837
|
+
*/
|
|
684
838
|
BlobInterceptor.prototype.intercept = function (request, next) {
|
|
685
839
|
var _this = this;
|
|
840
|
+
// 只处理 responseType 为 blob 的请求
|
|
686
841
|
if (request.responseType !== 'blob') {
|
|
687
842
|
return next.handle(request);
|
|
688
843
|
}
|
|
689
|
-
return next.handle(request).pipe(operators.switchMap(function (
|
|
844
|
+
return next.handle(request).pipe(operators.switchMap(function (event) { return _this.handleBlobResponse(event); }), operators.catchError(function (error) { return _this.handleBlobError(error); }));
|
|
690
845
|
};
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
846
|
+
/**
|
|
847
|
+
* 处理 Blob 响应事件
|
|
848
|
+
* @param event HTTP 事件
|
|
849
|
+
* @returns Observable<HttpEvent<any>>
|
|
850
|
+
*/
|
|
851
|
+
BlobInterceptor.prototype.handleBlobResponse = function (event) {
|
|
852
|
+
var _a;
|
|
853
|
+
// 只处理完整的响应事件
|
|
854
|
+
if (event.type !== http.HttpEventType.Response) {
|
|
694
855
|
return new rxjs.Observable(function (subscriber) {
|
|
695
|
-
subscriber.next(
|
|
856
|
+
subscriber.next(event);
|
|
696
857
|
subscriber.complete();
|
|
697
858
|
});
|
|
698
859
|
}
|
|
699
|
-
|
|
700
|
-
|
|
860
|
+
// 检查响应体是否为 JSON 类型(通常表示错误)
|
|
861
|
+
if (event instanceof http.HttpResponse && ((_a = event.body) === null || _a === void 0 ? void 0 : _a.type) === 'application/json') {
|
|
862
|
+
return this.convertBlobToJson(event.body);
|
|
701
863
|
}
|
|
702
864
|
return new rxjs.Observable(function (subscriber) {
|
|
703
|
-
subscriber.next(
|
|
865
|
+
subscriber.next(event);
|
|
704
866
|
subscriber.complete();
|
|
705
867
|
});
|
|
706
868
|
};
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
869
|
+
/**
|
|
870
|
+
* 处理 Blob 错误响应
|
|
871
|
+
* @param error HTTP 错误响应
|
|
872
|
+
* @returns Observable<HttpEvent<any>>
|
|
873
|
+
*/
|
|
874
|
+
BlobInterceptor.prototype.handleBlobError = function (error) {
|
|
875
|
+
var _a;
|
|
876
|
+
// 如果错误响应体是 JSON 类型的 Blob,转换为 JSON 对象
|
|
877
|
+
if (((_a = error.error) === null || _a === void 0 ? void 0 : _a.type) === 'application/json') {
|
|
878
|
+
return this.convertBlobToJson(error.error);
|
|
711
879
|
}
|
|
712
880
|
return new rxjs.Observable(function (subscriber) {
|
|
713
|
-
subscriber.error(
|
|
881
|
+
subscriber.error(error);
|
|
714
882
|
subscriber.complete();
|
|
715
883
|
});
|
|
716
884
|
};
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
885
|
+
/**
|
|
886
|
+
* 将 Blob 转换为 JSON 对象并抛出错误
|
|
887
|
+
* @param blob Blob 对象
|
|
888
|
+
* @returns Observable<HttpEvent<T>>
|
|
889
|
+
*/
|
|
890
|
+
BlobInterceptor.prototype.convertBlobToJson = function (blob) {
|
|
891
|
+
return new rxjs.Observable(function (subscriber) {
|
|
892
|
+
var reader = new FileReader();
|
|
893
|
+
reader.addEventListener('loadend', function () {
|
|
894
|
+
try {
|
|
895
|
+
var json = JSON.parse(reader.result);
|
|
896
|
+
subscriber.error(json);
|
|
897
|
+
}
|
|
898
|
+
catch (parseError) {
|
|
899
|
+
subscriber.error(parseError);
|
|
900
|
+
}
|
|
901
|
+
finally {
|
|
902
|
+
subscriber.complete();
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
reader.addEventListener('error', function () {
|
|
906
|
+
subscriber.error(new Error('读取 Blob 数据失败'));
|
|
728
907
|
subscriber.complete();
|
|
729
|
-
}
|
|
908
|
+
});
|
|
909
|
+
reader.readAsText(blob, 'utf-8');
|
|
730
910
|
});
|
|
731
|
-
reader.readAsText(blob, 'utf-8');
|
|
732
911
|
};
|
|
733
912
|
return BlobInterceptor;
|
|
734
913
|
}());
|
|
@@ -738,8 +917,10 @@
|
|
|
738
917
|
type: i0.Injectable
|
|
739
918
|
}] });
|
|
740
919
|
/**
|
|
741
|
-
*
|
|
742
|
-
*
|
|
920
|
+
* 提供 Blob 响应拦截器
|
|
921
|
+
* @returns Provider 配置对象
|
|
922
|
+
* @example
|
|
923
|
+
* providers: [providerDownBlob()]
|
|
743
924
|
*/
|
|
744
925
|
function providerDownBlob() {
|
|
745
926
|
return { provide: http.HTTP_INTERCEPTORS, useClass: BlobInterceptor, multi: true };
|
|
@@ -750,6 +931,7 @@
|
|
|
750
931
|
*/
|
|
751
932
|
|
|
752
933
|
exports.BlobInterceptor = BlobInterceptor;
|
|
934
|
+
exports.CacheHttpTemplate = CacheHttpTemplate;
|
|
753
935
|
exports.CacheInterceptor = CacheInterceptor;
|
|
754
936
|
exports.CustomTokenTemplate = CustomTokenTemplate;
|
|
755
937
|
exports.CustomTokenWithHeaderTemplate = CustomTokenWithHeaderTemplate;
|