只管拦截器可能批改申请和响应,但 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 readonlyreq.url = req.url.replace('http://', 'https://');

如果应用程序里必须更改 HTTP Request,请先克隆它并批改克隆,而后再将其传递给 next.handle()。 能够在一个步骤中克隆和批改申请,如以下示例所示:

// clone request and replace 'http://' with 'https://' at the same timeconst 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 propertyconst newBody = { ...body, name: body.name.trim() };// clone request and set its bodyconst newReq = req.clone({ body: newBody });// send the cloned request to the next handler.return next.handle(newReq);