关于 Angular HTTP Interceptor 中 Request 和 Response 的 immutable 特性

简介: 关于 Angular HTTP Interceptor 中 Request 和 Response 的 immutable 特性

尽管拦截器能够修改请求和响应,但 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);
相关文章
|
4月前
|
机器学习/深度学习 前端开发 JavaScript
源映射错误:Error: request failed with status 404 源 URL:http://localhost:8080/bootstrap/js/axios-0.18.0.js
源映射错误:Error: request failed with status 404 源 URL:http://localhost:8080/bootstrap/js/axios-0.18.0.js
114 0
源映射错误:Error: request failed with status 404 源 URL:http://localhost:8080/bootstrap/js/axios-0.18.0.js
|
1月前
|
Web App开发 监控 UED
如何解决Angular中的Error: HTTP request failed, call timeout问题
在Angular应用中,遇到HTTP请求超时错误`Error: HTTP request failed, call timeout`时,可通过多种途径解决。首先,可增加请求超时时间,Angular默认无超时限制,设置合理的超时时间如5秒有助于避免长时间等待无响应。其次,检查服务器响应时间,利用开发者工具监控网络请求,优化服务器端代码或调整超时值。最后,确认网络连接稳定性,使用`navigator.onLine`检测网络状态,并在不同网络环境中测试。这些策略共同作用,能够有效提升应用的稳定性和用户体验。
66 1
|
26天前
|
Python
【Azure 应用服务】Azure Function HTTP Trigger 遇见奇妙的500 Internal Server Error: Failed to forward request to http://169.254.130.x
【Azure 应用服务】Azure Function HTTP Trigger 遇见奇妙的500 Internal Server Error: Failed to forward request to http://169.254.130.x
Bad Request, Resolved [org.springframework.http.converter.HttpMessageNotReadableException,跟着视频仔细比对
Bad Request, Resolved [org.springframework.http.converter.HttpMessageNotReadableException,跟着视频仔细比对
|
2月前
|
API Java
解决HTTP 400 Bad Request错误的方法
解决HTTP 400 Bad Request错误的方法
|
2月前
|
Java API
解决HTTP 400 Bad Request错误的方法
解决HTTP 400 Bad Request错误的方法
|
4月前
|
JavaScript 前端开发
Angular.js 应用里如何发送 HTTP 请求
Angular.js 应用里如何发送 HTTP 请求
|
4月前
|
JSON API 开发者
什么是 HTTP 400 bad request 错误
什么是 HTTP 400 bad request 错误
|
4月前
|
存储 Web App开发 缓存
【JavaEE初阶】 HTTP 请求 (Request)详解
【JavaEE初阶】 HTTP 请求 (Request)详解
|
4月前
|
小程序
报错:http://edu.newsight.cn不在以下request合法域名列表中,请参考文档
报错:http://edu.newsight.cn不在以下request合法域名列表中,请参考文档