其实这是一个很简单的问题,答案当然是可以的。
有时候,我们在查看页面的response headers的时候,会发现相同域名下,不同的域名有时候返回的server是不同的,也就是他们其实是被部署在不同类型的服务器上。
实现的原理其实也很简单,不同类型的服务器都会提供反向代理功能。将满足一定条件的请求转发到另一台服务器上即可。
最近工作的内容也涉及到类似的功能,前提是这样的:我们的产品是一个简单的 CMS 产品,也就是每一个客户会拥有自己的独立域名,使用我们的网站产品,但是代码是同一套部署。
比如客户主站的域名是:www.ag.com。我们所有的产品可以部署到用户提供的一个子域名上: jobs.ag.com。这样用户只需要简单的将jobs.ag.com放到他们的网站入口上就可以了。
直到产品上线前一两个月,得到的需求是,客户不希望有子域名的存在,希望域名能够统一。也就是说,用户会在他们服务器上加设一层代理,所有的www.ag.com/jobs请求都会转发到jobs.ag.com上。
其实表面上看起来比较简单,只是一层简单的反向代理。但是细想,其实有很多问题。因为所有跟绝对路径相关的都会出问题。
举个例子:当用户访问:www.as.com/jobs/login点击登录以后,我们会跳转到/profile页面。一旦加了这一层反向代理以后,实际上的跳转页面也会变成:www.as.com/profile。然后代码就会走到客户的服务器上导致 404 出现。
因为我们实际上需要保证跳转的页面是:jobs.as.com/profile或者www.as.com/jobs/profile. 这样才能保证,请求会到达 CMS 系统的服务器。
另外一个现实是,我们的CMS系统最开始就没有考虑过根路径会有变化这个可能性。也就是说在系统里的跳转都是相当随意的。而且系统也比较老旧,前端同时存在jQuery和angularJS 的处理。
所以要解决这个问题就得包含以下几个方面:
- 假设这个CMS站的
prefix是jobs。(其实需要让不同的客户可以配置) - 确保所有的请求都支持prefix,也就是说:
jobs.as.com/jobs/和jobs.as.com能够同时处理。(这是为了方便处理绝对路径跳转和充分支持客户的反向代理) - 确保服务器端的页面能够正确跳转。
- 确保 HTML/CSS 中的资源请求标签(如:
a,<script>,img)标签能够正确处理。 - 确保 angularJS 中的页面跳转能够正确处理。(
ng-href) - 确保 JS 中的跳转能够正确处理。(
window.location)
下面再来一个个解释如何处理这些问题的
-
确保所有的请求都支持
prefix
这个其实很简单,不同的web框架有不同的处理方案。简单的说,就是服务器接收到request的时候判断一下是否包含你定义的prefix(这里是:jobs), 有的话去掉。这样就能保证所有
jobs.ag.com/jobs/*的请求都会和jobs.ag.com/*相同。不同的框架也有不同的方案,比如修改routes层。只需要确保所有的页面都能支持这个prefix, 甚至需要包含静态文件(js, css, images)。 -
确保服务器端的页面能够正确跳转。
所有服务器端的内容其实都相对比较简单。首先我们可能需要直到服务器端跳转的原理。
当我们请求A页面,A页面又跳转到B页面。实际上发生的事情是:- 请求
A页面的时候,A页面会在Response headers里添加一个字段叫做location。 - 浏览器如果接收到
Response Headers里的location字段,会重新发送一个GET请求到这个URL。
而且大多数
web 框架其实都会封装一个方法叫做doRedirection(),而你所有做的其实也就是在 doRedirection() 这里加上一层添加prefix在跟路径的逻辑。 - 请求
-
确保 HTML/CSS 中的资源请求标签。
这也是相对比较简单的,体力活。
在服务器端 response 之前截取到生成的 HTML,CSS 文件。穷举出所有肯能包含web 请求的标签,a,image等等,然后判断是否为绝对路径,是的话,加上prefix. -
确保 JS 中的跳转能够正确处理。(window.location)
-
确保 angularJS 中的页面跳转能够正确处理。(ng-href)