只管拦截器可能批改申请和响应,但 HttpRequest 和 HttpResponse 实例属性为 readonly
,这意味着其具备 immutability
个性。
这种个性是 Angular 框架无意为之的设计:应用程序可能会在一个 HTTP 申请胜利实现之前,多次重试申请。换言之,这意味着 Interceptor chain 能够屡次重新处理 (re-process
) 雷同的申请。如果拦截器能够批改原始申请对象,则重试操作将从批改后的申请开始,而不是从原始申请开始,这会给应用程序的解决引入极大的不确定性。
因而,Angular Interceptor 解决上下文中的 HTTP 申请和响应的 immutability
个性,确保拦截器在每次尝试中解决的是雷同的申请。
TypeScript 阻止开发人员设置 HttpRequest 对象中具备 readonly
的属性,看个具体的例子:
// Typescript disallows the following assignment because req.url is readonly
req.url = req.url.replace('http://', 'https://');
如果应用程序里必须更改 HTTP Request,请先克隆它并批改克隆,而后再将其传递给 next.handle()。能够在一个步骤中克隆和批改申请,如以下示例所示:
// clone request and replace 'http://' with 'https://' at the same time
const secureReq = req.clone({url: req.url.replace('http://', 'https://')
});
// send the cloned, "secure" request to the next handler.
return next.handle(secureReq);
上面是 SAP Spartacus Interceptor 中应用 clone 办法去批改一个 HTTP Request 的具体例子:
[图片]
TypeScript 的 readonly 属性,并不能阻止 Request body 字段被 deep update
.
下列代码能工作,然而却是一个蹩脚的设计,起因如前所述:如果该 Interceptor 被反复调用,则每次调用会在前一次调用批改的 HTTP Request 的根底上再次进行批改,一直造成 Side Effect
:
req.body.name = req.body.name.trim(); // bad idea!
Angular 举荐的做法顺次是:
- 对 Request body 进行 copy,并批改 copy 版本
- 应用 HTTP Request 的
clone
办法,克隆申请对象。 - 用批改后的 body copy 版本,替换克隆进去的 HTTP 申请的 body 字段。
伪代码如下:
// copy the body and trim whitespace from the name property
const newBody = {...body, name: body.name.trim() };
// clone request and set its body
const newReq = req.clone({body: newBody});
// send the cloned request to the next handler.
return next.handle(newReq);