jingzhiMo.github.io
jingzhiMo.github.io copied to clipboard
记一次本地前后联调的过程
背景
最近项目组的的后端业务开始拆分,把部分用户与业务需求拆分;在原来的时候,用户的请求与业务请求都是由同一个后端项目支持;现在由于子项目不断扩充,不同的子项目之间的账号信息需要同步。
分析
更改前
步骤:
-
request user
, 前端向后端请求用户信息(忽略登录过程) -
response token
,后端返回用户的token;前端拿到token存储到 storage -
req/res
前后端进行业务数据的交流
更改后
步骤:
-
request user
前端a.example
向user.example
用户后端请求 用户信息(忽略登录过程) -
response token
,用户后端返回用户的token,设置到 cookie; -
req/res data
前端与业务后端b.example.com
进行数据交流
不同点
这次更改的不同点主要是:
- 请求的用户信息的域名不一致;更改后的会存在跨域问题;
- 前端存储用户token的方法不同,前者存储在 storage ;后者存储在 cookie
- 前者由于用户信息存储在 storage;因为在请求数据的时候,需要在请求拦截器加一层,把用户的 token 加到 xhr 的请求头,让服务器能够拿到对应的用户信息;后者用户信息存储在 cookie;那么前端不需要做特别的处理,cookie 自动加入 header 发送到服务器。
解决方案
由于涉及多个域名,因此原有使用 storage 的方案没有 cookie 那么灵活。OK,涉及多个域名,那么最常见的 CORS 跨域的手段必不可少;前端在这个过程处理不多,只需要设置 xhr 的withCredentials: true
;则浏览器会在请求跨域的时候,把对应域名的 cookie 带上到请求。
但是在开发的时候,尽管后端同学已经允许请求跨域;但是看到 network 会出现部分 OPTIONS
请求;然后再发出真正的请求;在这之前,有了解过,这是浏览器的安全机制,先发出 OPTIONS
的预检请求,如果服务器允许的话,才发出真正的请求,这个过程对前端来说是透明的。但是观察到,只是部分请求有预检,并不是所有请求都有预检,那么对于哪些请求才需要呢?然后找到了 mdn cors 相关文章,文章对于情况说的比较明白,这里简单总结几点;
- 浏览器对“简单请求”不做预检(preflight);这些请求包括:
GET
,POST
,HEAD
这三种 - 请求头(headers)需要在白名单内,除了浏览器自动加的
user-Agent
,referer
等, 白名单的请求头有:- Accept
- Accept-Language
- Content-Language
- Content-Type(仅包括:application/x-www-form-urlencoded, multipart/form-data, text/plain 三种)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问
- 请求中没有使用 ReadableStream 对象。
到现在为止,请求就能够正常发出了,用户的登录与业务数据交流也完成了;但实际上也遗留了一个问题:线上环境的业务请求不是跨域的,只是本地与后端同学调试才是,那么能不能本地也不做跨域的请求呢?
后续
本地测试前置条件:
- 前端地址:
http://localhost:8080
- 用户后端项目地址:
user.local.com
- 业务后端项目地址:
a.local.com
由于本地开发的时候,本地通常是访问http://localhost:8080
;因此在请求完user.local.com
的时候,后端返回的用户信息 cookie 是存在域名 *.local.com
;所以当我们请求业务数据的时候a.local.com
的时候,浏览器自动把 cookie 带过去。
因此想在请求业务数据a.local.com
的时候不跨域而又需要a.local.com
;那么本地访问的地址也是要*.local.com
;顺理成章,我们把本地的host配一下,a.local.com:8080
,这个时候有个疑问,因为不同协议(http/https),不同域名,不同端口的情况下,都属于跨域,那么实际上 cookie 还是不会发过去...
But, 对于我这种面向google的,还是去查一下,因为之前只停留在印象阶段,没有去实际应用;在stackoverflow 的回答中,指出 cookie 的传输不受端口的跨域限制。
至此,我们前端开发的域名就与后端一致了;那么后端的接口怎么发送到后端同学那边呢,这里我们可以使用webpack-dev-server代理我们的请求;webpack dev-server的简略配置:
devServer: {
proxy: {
// 通常针对特定规则的请求
'^/backend': {
// 后端同学的ip地址
target: '172.x.x.x'
}
}
}
总体起来是两点:
- 本地配host与测试用户服务器域名为同一个父域名的地址;
- 使用webpack-dev-server 代理请求,指定到业务服务器的地址
总结
这次解决的问题实际上也比较简单;但是对一些之前认知的知识只停留在理论阶段,在实际应用上并没有实践好;顺便也巩固之前一些模棱两可的答案。end...