json-srver go version开发笔记

json-server竟然不支持POST?

上周在进行开发的时候,由于同事的后端服务并没有开发完成,并且没有数据可以使用,因此在开发过程中是需要有一个辅助服务器来进行开发,其功能很简单,应该是在收到请求之后,无脑返回假数据就ok了,此时想到了之前听说过的json-server,js是使用node进行开发的一款mock serever,他能读取json文件,然后在使用get请求访问时返回对应路径对应的数据。例如下面的数据配置好之后,使用get请求来访问对应的path,就能拿到相应的数据了。说到这里,不得不感叹下前端开发的黑科技是真的很多啊。

1
2
3
4
{
"/path":123,
"/path1":[1,2,3]
}

于是费了老大劲安装json-server,为啥说费老大劲,因为之前一直没接触过node、npm这些东西,安装的时候还一直报错SSL Error: CERT_UNTRUSTED(解决方法是npm config set strict-ssl false),安装后进行测试,结果发现json-server只能处理GET请求,如果接收到POST的请求,直接就异常了。。。我真是整个人都不好了,不过想了想,json-server本身是给前端开发的,而前端大多数情况下也是从后端使用GET方法获取假数据,真是没脾气啊。。没办法,只好自己造个轮子了,毕竟功能也不是特别复杂,在使用go的情况下当天实现了一个简版的。这周末简单构思了一下,实现了一个功能稍微复杂一些的json-server-go。

主要包括以下功能:

  • 不管接收到什么请求,都会将请求打印到屏幕上
  • 读取json文件,使用最外层的key作为path,value作为返回数据
  • 当json文件修改后实时更新server

项目地址

设计过程

虽然go对于对于http开发支持十分友好,但是由于增加了热更新的功能,所以需要较好的可控性,包括http server启动和关闭。因此开发的时候并没有使用最常见的http.HandleFunc和listenAndServ而是使用了较为底层的http.Server和http.Handler。其实使用ListenAndServe时实际上也是创建了一个http.Server,但是因为我们要使用Server的Shutdown方法进行退出,所以没有使用封装的更简洁的版本,在此之后,对于path的处理,我们可以使用HandleFunc但是考虑到Server刚好有一个Handler接口,并且即便是有100个path他的功能也是一样,so最终还是使用了Handler方法,方法的详细文档官网有,这里就不再赘述了。http server的设计就这些啦。

然后就是文件服务这边的设计,由于需要监听文件改动,网上找了一下,找到了fsnotify这个项目,看了下实现也比较简单,star也最多,并且后续有可能收录到标准库里面,因此文件监控使用的是它,逻辑也比较简单,就是检测到文件修改就进行重载,之后加载完数据后传递给http server进行重启。

项目路径如下:

  • jserver.go(main)
  • floader
    • floader.go
  • server
    • server.go
  • vendor

使用了vendor目录进行依赖库的管理和存放,觉得这样比较简洁:)

在使用vendor的过程中发现了一个好物,安利一下。他能直接将环境依赖下载到本项目的vendor下面,很是方便。

中间遇到的一些坑

中间遇到了一些细枝末节的坑,记录一下,权当反思并且希望读者可以不要再犯同样的错误啦。

文件热加载相关

  1. 在复制测试代码时,由于没有看仔细,没有使用管道阻塞住函数返回,导致创建watcher之后就defer close,结果就是监听了被关闭的管道。。。结果你懂得
  2. vim在编辑文件之后保存,会对文件进行替换!!!是的,你没看错,使用vim保存文件之后是会导致文件被重命名然后创建一个新的文件将其覆盖,推测和vim的备份机制有关,vim再打开备份机制的情况下保存会备份一个file.back~这种备份文件。这个坑耽误时间比较久,后来是通过echo > 和ls -i这种方式确认vim这个机制。
  3. 在使用json.Unmarshal的时候,如果每次不对变量进行清空,例如,每次都json.Unmarshal(bytes_list,&map_cache),会导致cache的累加,正确的方式应该是每次map_cache = make(…)
  4. 由于go的多线程异步创建太方便了,所以一定要确保该同步的地方一定要同步!!我在开发过程中就犯了一个很低级的错误(不是第一次犯了)。场景是,通过管道进行控制的时候,管道尚未make赋值的时候就对其进行了监听,而后才c = make(chan),这种情况导致的就是程序正常逻辑终端卡死,因为消费者监听的管道和生产者不再是同一个。正确的方式应该是,在管道变量初始化之后,再对其进行监听。
  5. 使用Server + Handler这种方式进行路径绑定,它的优先级是要比HandlerFunc要高的

转载请注明来源链接 http://just4fun.im/2018/07/28/jserver/ 尊重知识,谢谢:)