一、介绍
simple-server是一个使用NodeJS编写的简单服务,支持静态资源、请求转发、数据mock。非常适合在开发、测试环境使用。
simple-server具有如下特点:
- 🎄 集成mock服务(服务端数据模拟),即支持使用静态JSON文件,也支持返回JS动态生成的数据,支持高级拓展(如根据前端上行参数自定义返回不同结果);
- 🌐 默认支持跨域访问;
- 💪 支持post传输最大100M的大文件(100M足够一般的开发、测试需求了。请注意,如果使用nginx等其他服务代理时,这些服务本身也有文件大小限制的,没记错的话nginx默认限制1M,tomcat默认限制2M,最终能支持的大小是由所有这些服务中的下限决定的);
- 🔥 针对请求转发场景进行了日志优化,便于排查问题(由于目标场景是请求量不大的测试或者开发环境,所以日志被格式化便于阅读,若用于生产环境请稍加修改)。
- 👫 集成了PM2支持,只要几个命令即可做到异常时自启动、配置/mock文件修改时自启动,开机自启动(开启自启不支持window系统),部署运维方便;
- 🛠 可作为静态文件服务器。
- 🚀 支持解析gzip或deflate压缩过的响应内容。
二、应用截图
输出日志截图:
应用状态截图(使用pm2部署,App名称为simple-server-${config.port},便于知悉当前服务所占用的端口号):
三、项目部署
本项目使用pm2进行项目的启动与维护。
3.1、安装依赖
npm run installDependencies
3.2、启动项目
请先将项目根目录的config-example.js文件重命名为config.js文件,然后根据实际需要修改对应配置,然后再进行后续操作(配置项中各参数的说明见后文)
注:以下命令需在项目根目录下执行,其中部分命令可视为pm2对应命令的别名,可以在任意目录下通过直接使用pm2命令达成。
# 初次启动(在项目根目录下执行) npm run start # 重启(在项目根目录下执行) npm run restart
3.3、开机自启动
执行下述命令,pm2会给出一串脚本命令,在终端中复制粘贴该命令并回车执行即可(有时候会直接执行成功然后告诉你执行成功了,这时候就不用再复制命令手动去执行了)。
# 在项目根目录下执行 npm run getShellUsedToStartProjectAfterReboot
3.4、查看项目日志
# 在项目根目录下执行 npm run log
3.5、停止和删除项目
删除项目:
# 在项目根目录下执行 npm run stop
从PM2项目清单中删除项目:
# 在项目根目录下执行 npm run delete
四、配置文件规则说明
4.1、设置服务端口
修改配置文件中的config.port字段,默认启用端口号为3456。示例配置如下:
const config = { // ... port: '3456', // ... } module.exports = config
4.2、请求代理/转发
修改配置文件中的config.proxyTable字段即可。示例如下:
const config = { // ... proxyTable: { '/apis/proxy-test': { target: 'http://test.api.com', changeOrigin: true, pathRewrite (path, req) { return path.replace('/apis/proxy-test', '/apis/proxy') }, }, '/apis/proxy': { target: 'http://production.api.com', changeOrigin: true, }, }, // ... } module.exports = config
如上配置对应的解释描述如下:
- 发至本服务的路径以/apis/proxy-test开头的请求会被转发到http://test.api.com/apis/proxy下。例如,发至本服务的/apis/proxy-test/v2/queryDate.do请求会被转发到http://test.api.com/apis/proxy/v2/queryDate.do。
- 这里采用“越具体的配置,优先级越高”的规则,即如果某个请求符合多条规则,其中最具体的规则会生效。如,若同时配置了针对/apis/proxy和/apis/proxy/v2的转发规则,则/apis/proxy/v2/test.do请求会依据/apis/proxy/v2的规则被转发,其他如/apis/proxy/v1/test.do的请求则会依据/apis/proxy的规则被转发。
说明:程序会自动对代理请求返回的结果进行备份,备份目录为/data/mock/proxy,生成的文件名是根据请求地址自动生成的。大部分时候不需要搭理这些备份文件。但是如果你正好也同时使用用本服务做mock服务,则可以拷贝这些文件作为mock数据文件,具体用法见后文描述。
本项目针对请求代理/转发的场景,针对性的进行了日志输出的优化,可以通过修改config.logLevel的值来切换不同的日志打印丰富度,目前支持以下两个枚举值:
- simple:仅打印核心内容,日志量少,有可能缺少排查问题的关键信息。
- normal: 打印内容丰富,排查问题时信息更丰富,但相对的,日志量会大很多。
4.3、返回JSON静态数据
修改配置文件中的config.jsonTable字段即可。示例配置如下:
const config = { // ... jsonTable: [ '/manage2/intention/list', '/manage2/carInsurance/queryDetails', '/manage2/carInsurance/updateQuotation', '/manage2/order/list', '/manage2/order/queryDetails', '/manage2/order/updateSalesman', '/manage2/order/update' ], // ... } module.exports = config
如上配置对应的解释描述如下:
若有发至本服务的路径精确匹配/manage2/intention/list的请求,则服务器会将文件/data/mock/json/manage2-intention-list.json的内容予以返回。
注意:你可以在启动服务器之前,先在/data/mock/json目录下手动建立对应的json文件,并填充数据;如果您未提前手动建立对应json文件,程序会自动帮你新建一个内容为{}的json文件,内容还需您自行填充。一般来说用后面这种方法会比较方便,修改了文件后程序会自动重启的,不需要手动重启服务。
小技巧:可以将程序在/data/mock/proxy目录下生成的备份文件拷贝至此处使用。
4.4、返回JS自定义数据
修改配置文件中的config.customTable即可。示例配置如下:
const config = { // ... customTable: [ '/great/what' ], // ... } module.exports = config
如上配置对应的解释描述如下:
若有发至本服务的路径精确匹配/great/what的请求,服务器会将/data/mock/custom/great-what.js文件中导出的函数予以调用,并将函数调用后的返回值发送至前端。
注意:你可以在启动服务器之前,先在/data/mock/custom目录下手动建立对应的js文件,在该js文件中通过module.exports导出一个函数,该函数需要返回一个json数据(也可以让程序自动创建该文件,程序自动创建的文件会默认写入module.exports = (req) => { return {} }来作为占位内容),该函数可接收一个表示请求的req参数,所以你可以根据req来判断请求方式、请求头、接口上行参数等来进行返回内容的高级自定义。
说明:之所以在自定义js文件中导出函数而非直接导出数据,是为了便于服务器返回动态内容。
说明:安装程序依赖时默认安装了mockjs模块,你可以在代码中require该模块来生成一些动态mock数据,如下所示。
const Mock = require('mockjs') const returnRes = (req) => Mock.mock({ // 属性 list 的值是一个数组,其中含有 1 到 10 个元素 'list|1-10': [{ // 属性 id 是一个自增数,起始值为 1,每次增 1 'id|+1': 1 }], // 在接口里返回请求方式 method: req.method, // 在接口里返回前端传参 params: (() => { if (req.method === 'POST') { return req.body } else if (req.method === 'GET') { return req.query } return 'Neither post nor get request' })(), }) module.exports = returnRes
4.5、设置静态文件服务
将您的前端文件或其他静态文件放置于/public目录下,然后修改配置文件中的config.public,该值将与/public目录直接映射。config.public的默认值为”/test”,即”/test/index.html”将会访问public目录下的index.html文件。示例配置如下:
const config = { // ... public: '/static', // ... } module.exports = config
如上配置对应的解释描述如下:
假设我们在/public目录下存放了index.html、css/style.css、scripts/app.js等文件。那么发至本服务的路径精确匹配/static/index.html的请求,将访问/public/index.html文件。
说明:
- 在上述配置下,请求/static和请求/static/index.html实际访问的是同一个文件,因为程序设定的默认首页为index.html。
4.6、重定向
可通过修改配置文件中的config.redirect字段设置重定向规则。示例如下:
const config = { // ... redirect: { movedPermanently: { // 301 redirect 永久重定向 '/a': '/b', }, movedTemporarily: { // 302 redirect 临时重定向 '/vendor/assets/zepto.min.js': 'http://localhost:3000/vendor/assets/zepto.min.js?v=20191122', }, }, // ... } module.exports = config
如上配置对应的解释描述如下:
- 在上述配置规则下,发至本服务的路径精确匹配/a的请求将被301永久重定向到/b请求;发至本附的路径精确匹配/vendor/assets/zepto.min.js的请求将被302临时重定向到http://localhost:3000/vendor/assets/zepto.min.js?v=20191122。
五、在线访问项目说明文档
启动本服务后,可通过访问/help来访问项目说明文档。
六、使用nginx等做反向代理
如果使用nginx进行代理,则可能不会走express的静态服务,这时候需要在nginx配置类似下面这样的配置(假定config.public配的是static):
location ^~ /static/ { allow all; alias /www/wwwroot/www.example.com/simple-server/public/; } location ^~ /screenshots/ { allow all; alias /www/wwwroot/www.example.com/simple-server/screenshots/; }
然后为了安全起见,我们并不希望simple-server下的服务端源码被用户访问到,所以还需要增加这样的配置(示例里是禁止访问markdown文件和js文件,不过这不会影响上面的配置,即:public和screenshots下面的js和markdown文件不受影响,仍能正常访问):
location ~* \.(js|md)$ { root /www/wwwroot/www.example.com/simple-server/; deny all; }
License/许可
MIT协议。免费开源,可以随意使用,但因使用而产生的问题请自行负责。