前端配置本地代理方法总结

综合技术 2018-12-08 阅读原文

在前后端分离的开发中,前端的静态资源存于本机上,通过 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 半天回不了结果。而且 SwitchyOmegaCharles 都不能批量复制修改,得一个一个在图形界面改,有的时候就很麻烦(比如将线上环境切到后端的开发环境)。

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。不过作为前端开发,多熟悉下 CharelsNginx 也是个不错的选择。

稀土掘金

责编内容by:稀土掘金阅读原文】。感谢您的支持!

您可能感兴趣的

NGINX按天生成日志文件的简易配置 NGINX按天生成日志文件的简易配置 0x01 最近后端童鞋遇到一个小需求,拆分nginx生成的log文件,最好是按天生成,看着她还有很多bug待改的状态,我说这个简单啊,我来吧。曾经搞node后端的时候,这些东西都so ...
老司机配置Nginx用到的实用配置 隐藏nginx、openresty版本号隐藏nginx、openresty的版本号有什么用? 假设一个场景,nginx被爆出0.9-1.5的版本被爆出一个0day漏洞, 攻击者会先大量扫描匹配的nginx版...
NGINX Unit Now Supports TLS and JavaScript Apps wi... When our engineering team showed me the initial code for TLS support a few weeks ago, I blocked off a few hours to get t...
Nginx HTTP/2和mp4模块拒绝服务预警 报告编号:B6-2018-110901 报告来源:360-CERT 报告作者:360-CERT 更新日期:2018-11-09 0x00 事件背景 Nginx 11月6日的安全更新中,修复了三个可导致拒绝服务的...
nginx反向代理webSocket配置 最近在做项目的时候用到了webSocket协议,而且是在微信小程序中用到了webSocket,微信小程序中使用wss协议的时候不能设置端口,只能使用默认的443端口。我擦,我的https已经监听了443端口,webSocket再去监听443...