给客户端造模拟数据
1.1、为什么要给客户端造模拟数据

现在的软件开发都是分工非常明确的,一个开发团队通常都会有:服务端开发人员若干Android端开发人员若干iOS端开发人员若干Web前端开发人员若干、 这些端是靠接口把他们联系在一起的,接口就是这些端进行交换数据的通道。

通常,客户端Android端iOS端Web前端)需要的数据比较多一些。客户端要向服务端要数据,就必须定义规则,规则就是接口

接口是怎么定义的呢?接口通常是根据产品经理的原型制定的。

接口定义好之后,服务端客户端分别基于这个定义好的接口进行实现。

但是刚定义好,客户端是无法向服务端要数据的,因为服务端还没实现好呢? 而客户端在开发的时候就要要数据,客户端是严重依赖数据的, 因为客户端通常是展示UI,而UI中的数据基本上来自于服务端。 这怎么办呢?客户端总不能等着服务端实现好了再开工吧! 对于这种情况,有很多的方法可以解决:

初级一点儿的程序员的做法:造一堆假数据在自己的代码里。这种方法显然是不合理的,造成代码难以维护,正式发布的时候,一旦忘记了删除掉这些假数据,会出现很多的Bug。

高级一点儿的程序员的做法:用一些Mock库。Mock的代码与实际的代码是分开的,这样确实很好, 但是这个有点独乐乐的味道,因为每个端都要这么干,团队成员可能有很大的学习成本,因为这种方式不统一,而且还不是真实的网络环境。 当你切换到真实的网络环境下很可能会出现预料不到的问题。

最高级的做法:利用接口文档自动生成Mock接口。因为定义接口一定要写接口文档, 有很多工具可以根据接口文档生成Mock接口,比如EasyMock,当然,这个也需要一定的学习成本,但是这个 学习成本是非常低的,语法非常简单,而且只需要些文档的那个人学,但是是整个团队受益,客户端再也不用各自学一些Mock库了,而且这是真实的网络环境, 只是没有逻辑而已。这样,客户端开发起来就会顺畅很多,可以将问题提前暴露出来, 而不是等到集成测试阶段一下子爆发。还可以提高开发效率。

退而求其次的做法:但是很多团队仍然不愿意使用这种方法,因为他们说,把自己的接口文档放在公网上,这个不安全。这时候, 就是我们的ngnix上场的时候了。我们将客户端需要的接口数据按照一定的规则放在ngnixhtml目录中,利用rewrite功能把对应接口的数据返回给客户端。

下面是我ngnix的一个配置示例:

location / {
    root html;
    index index.html index.htm;

    if ($http_x_user_agent ~ "com\.unionx\.edu\.online") {
         rewrite ^/(.*)$ /edu_online/$1-response-body.json break;
    }

    if ($http_x_user_agent ~ "com\.unionx\.yilingdoctor") {
         rewrite ^/(.*)$ /yilingdoctor/$1-response-body.json break;
    }
}

说明:

Android端发起HTTP请求的时候, 会在X-User-Agent请求头里面包含这个Android App的包名。

iOS端发起HTTP请求的时候, 会在X-User-Agent请求头里面包含这个iOS AppBundleID

iOS AppBundleIDAndroid App的包名类似,都是一个App的唯一标志, 在项目开始之前,项目经理应该尽量确保他们两个设置成一样的字符串(一般是域名倒置),这样就统一了,当然不一样也可以,只是麻烦一些。

这里是匹配包名或者BundleID的,匹配到就可以确定是哪个App了。 这样一个ngnix就可以为不同的App的接口造模拟数据了。

这里没有使用HTTP标准的请求头User-Agent, 而是自定义了一个X-User-Agent, 这是因为在浏览器里面使用XHR发起请求的时候,浏览器为了安全考虑, 是不允许修改User-Agent这个请求头的值的, 所以我们才自定义了一个X-User-Agent,表示对User-Agent的扩展。 具体可以参考:https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-setrequestheader()-method

注意:对于HTTP POST请求,会出现问题,具体解决办法请看POST请求静态资源,返回405 Not Allowed