内容简介:在前后端分离的开发中,前端的静态资源存于本机上,通过 localhost 访问,如果直接调用服务端 api 则会因为跨域的问题不能正常访问。解决跨域问题可以通过 JSONP 或者让服务端设置最近接手了一个项目,代理配置过程很有意思,记录下来。简单描述下场景:前端配置代理最常用的就是利用webpack的devServer.proxy了。
在前后端分离的开发中,前端的静态资源存于本机上,通过 localhost 访问,如果直接调用服务端 api 则会因为跨域的问题不能正常访问。解决跨域问题可以通过 JSONP 或者让服务端设置 Access-Control-Allow-Origin 解除限制。但是并不是所有接口都可以这么搞的,所以一般需要前端自己配置代理来解决跨域问题。
背景
最近接手了一个项目,代理配置过程很有意思,记录下来。简单描述下场景: projectA 是一个普通的页面,但里面部分区域和部分弹层是通过 iframe 的形式引用的 projectB ,而且后端接口限制出于安全考虑 只接受来自指定域名 ( *.server.com ) 的请求 ,对于来自 localhost 或者 IP 的请求会被直接重定向至 server 域的登陆接口( server.com/login )。需要同时启动 projectA (localhost:8087)和 projectB (localhost:8085)两个项目。
devServer.proxy大法
前端配置代理最常用的就是利用webpack的devServer.proxy了。
我首先尝试的是在 projectA 的 devServer 中这样配置:
devServer: {
proxy: {
'/api': { // 需要直接代理到线上环境的接口
target: 'http://ad.server.com',
changeOrigin: true,
headers: {
// 后端要校验请求源,那改下 host 或者 origin 不就美滋滋了?
Host: 'ad.server.com',
Origin: 'ad.server.com'
},
},
'/apitest': { // 需要与后端联调的接口
target: '10.8.0.1:9909',// 后端本地开发环境
},
'/iframe': {
target: 'http://localhost:8085',
}
// 另外还有 iframe 里的 api 调用指向线上环境
}
}
复制代码
然而,后端接口残酷地给跳转到登陆接口去了 :sob:。猜想一下可能后端的接口是通过 cookie 来判断当前登陆域的,从 localhost 过去的请求不带 cookie。后来尝试发现在 proxy的headers里再增加 cookie 即可破跳转,但是请求过去返回结果还是在报错,后端表示仍然是认证失败。
SwitchyOmega
既然从 localhost 访问不行那只好就从server.com 这个域来访问了。简单的做法就是利用浏览器插件 SwitchyOmega 配置代理。即 http://ad.server.com/* 的所有请求全部指向 localhost8087, http://ad.server.com/iframe/* 的请求全部指向 localhost8085, 然后将 api 的部分拎出来直接代理回线上。
坑爹的是有的静态资源也不需要被代理到本地,例如 http://ad.server.com/static/* 本地可能根本就没有,得重新指回到线上。这时候 iframe 里的 projectB 又开始作妖了,里面的静态资源存于好几个目录,得挨着挨着配置,最后出来的完整配置就变得无比长。
SwitchyOmega 既可以对全局进行代理设置,也可以对单独域进行设置(点开 SwitchyOmega 看到下面那个漏斗便是)。这就导致了我的噩梦:期间我在做其他项目的时候进行一些小流量测试也是在用这个 SwitchyOmega 代理,也会涉及到对 server.com 域的修改,几番折腾后已经分不清到底当前是在全局代理还是对单独域代理了(而且实际项目中不止 server.com 这一个域),每日疑惑便是:“现在到底把哪个域代理到哪去了?”
为了避免这种困惑最后只能左手一个 Chrome,右手一个 Canary(Chrome 的开发版),两个不同浏览器分别独立的 SwitchyOmega 配置。
Charles
后来感觉用 SwitchyOmega 这种上网 工具 来做开发不太专业,而且切换浏览器来代理的做法也实在不方便,就改用 Charels 。开启代理后利用其 Map Remote 功能,可以配置具体哪些请求代理到哪个地方去。因为其界面是图形化的,功能也比较强大,把 SwitchyOmega 里的配置抄一份过来便可用了。比 SwitchyOmega 相比,不用再把本就应该代理到线上的静态资源再写一遍,所以配置会少一些。
最后让我放弃 Charles 的原因是:实在太卡了 :sob:。同时配置了多个 url 代理的情况下,电脑风扇转得飞起,请求一个被代理了的 url 半天回不了结果。而且 SwitchyOmega 和 Charles 都不能批量复制修改,得一个一个在图形界面改,有的时候就很麻烦(比如将线上环境切到后端的开发环境)。
Nginx
想更灵活地复制修改配置,当然最理想的就是一个可编辑的配置文件了。 Nginx 正好可以非常方便的修改配置文件,而且本地启一个 Nginx 进程不会像 Charels 那么耗资源。最后配置出来的 Nginx 大概长这个样子:
http:{
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream localhost8083 {
server 127.0.0.1:8083;
keepalive 2000;
}
upstream localhost8087 {
server 127.0.0.1:8087;
keepalive 2000;
}
upstream rd {
server 10.8.0.1:9909;
keepalive 2000;
}
upstream server {
server ad.server.com;
keepalive 2000;
}
server {
listen 80;
# api接口用于和后端开发联调
location ^~ /api/{
proxy_pass http://rd;
proxy_set_header Host $host:$server_port;
}
# 代理 projectA 的页面
location ~ /(path1|path2|path3)/ {
proxy_pass http://localhost8087;
proxy_set_header Host $host:$server_port;
}
# 代理 projectA 的静态资源
location ^~ /projectA_static/ {
proxy_pass http://localhost8087;
proxy_set_header Host $host:$server_port;
}
# 代理 projectA 的 hot-update
location ~ \.hot-update.js$ {
proxy_pass http://localhost8087;
proxy_set_header Host $host:$server_port;
}
# 代理 projectB 的 iframe 页面
location ~ /(path_iframe1|path_iframe2|path_iframe3) {
proxy_pass http://localhost8085;
proxy_set_header Host $host:$server_port;
}
# 代理 projectB 的静态资源
location ^~ /projectB_static/ {
proxy_pass http://localhost8085;
proxy_set_header Host $host:$server_port;
}
# 剩下的请求正常走 server.com 线上环境
location / {
proxy_pass http://server;
proxy_set_header Host server;
}
}
复制代码
利用 Nginx 灵活的规则,可以合并一些相似的代理规则,不用像配置 Charles 那样得一个一个自己粘贴了。另外还有个好处就是可以灵活管理自己的代理环境, 如果今后再有像这种代理比较麻烦的项目,可以分别拆成两个 nginx.conf 文件,使用时指定用哪个 conf 文件即可。如果用 Charles 管理的话,所有代理都一个配置列表里面,代理多了之后会非常难以维护。
不过本机用 Nginx 代理一般得配合改 hosts 文件,在 hosts 文件里将 test.server.com (自己瞎编的一个域,这里满足 *.server.com 就能通过后端的校验) 指向 localhost即可。启动 Nginx 指定监听 80 端口,这样访问 test.server.com 的时候(实际上访问的就是 localhost:80 ) 就会被 Nginx 给代理了。配置好了之后,访问 ad.server.com/ 就是线上环境,改成 test.server.com/ 就是本机环境了,无痛切换,非常舒服。
总结
以上几种办法都在一定场景下能实现代理的需求。后来发现社区有专门的轮子 xswitch 、zan-proxy。不过作为前端开发,多熟悉下 Charels 和 Nginx 也是个不错的选择。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 前端路由&webpack基础配置
- 前端快速入门Nginx配置
- AngularJS + CoffeeScript 前端开发环境配置详解
- AngularJS + CoffeeScript 前端开发环境配置详解
- 从0搭建前端项目架构-webpack配置
- 前端小纠结--VS Code调试配置分享
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML5经典实例
Christopher Schmitt、Kyle Simpson / 李强 / 中国电力出版社 / 2013-7 / 48.00元
《HTML5经典实例》对于从中级到高级的Web和移动Web开发者来说是绝佳之选,它帮助你选择对你有用的HTML5功能,并且帮助你体验其他的功能。个技巧的信息十分丰富,都包含了示例代码,并详细讨论了解决方案为何有效以及如何工作。一起来看看 《HTML5经典实例》 这本书的介绍吧!