2017-01-23 15:39:41 +08:00
Koa2 RESTful API 服务器脚手架
=============================
2017-01-23 01:12:24 +08:00
2017-01-23 15:51:28 +08:00
这是一个基于Koa2的轻量级RESTful API Server脚手架, 支持ES6。
2017-01-23 01:12:24 +08:00
2017-01-23 15:51:28 +08:00
约定使用JSON格式传输数据, POST、PUT、DELET方法支持的Content-Type为`application/x-www-form-urlencoded、multipart/form-data、application/json`可配置支持跨域。非上传文件推荐application/x-www-form-urlencoded。通常情况下返回application/json格式的JSON数据。
2017-01-23 01:12:24 +08:00
可选用mongodb、redis非关系型数据库和PostgreSQL, MySQL, MariaDB, SQLite, MSSQL关系型数据库, 考虑RESTful API Server的实际开发需要, 这里通过sequelize.js作为ORM, 同时提通过Promise执行SQL直接操作Mysql数据库的方法( 不管什么方法, 注意安全哦) 。
此脚手架只安装了一些和Koa2不冲突的搭建RESTful API Server的必要插件, 附带每一个插件的说明。采用ESlint进行语法检查。
2017-01-23 03:38:59 +08:00
因此脚手架主要提供RESTful API, 故暂时不考虑前端静态资源处理, 只提供静态资源访问的基本方法便于访问用户上传到服务器的图片等资源。基本目录结构与vue-cli保持一致, 可配合React、AngularJS、Vue.js等前端框架使用。在Cordova/PhoneGap中使用时需要开启跨域功能。
2017-01-23 01:12:24 +08:00
**免责声明:** 此脚手架仅为方便开发提供基础环境,任何人或组织均可随意克隆使用,使用引入的框架需遵循原作者规定的相关协议(框架列表及来源地址在下方)。采用此脚手架产生的任何后果请自行承担,本人不对此脚手架负任何法律责任,使用即代表同意此条。
目前暂未加入软件测试模块,下一个版本会加入该功能并提供集成方案。
China大陆用户请自行优化网络。
2017-01-23 15:39:41 +08:00
开发使用说明
------------
2017-01-23 01:12:24 +08:00
```
$ git clone https://github.com/yi-ge/koa2-API-scaffold.git
$ cd mv koa2-API-scaffold
2017-01-24 23:19:44 +08:00
$ npm install
2017-01-23 03:38:59 +08:00
$ npm run dev # 可执行npm start跳过ESlint检查。
2017-01-23 01:12:24 +08:00
```
2017-01-23 15:39:41 +08:00
访问: http://127.0.0.1:3000/
2017-01-23 01:12:24 +08:00
2017-01-23 15:39:41 +08:00
调试说明
--------
2017-01-23 01:12:24 +08:00
```
2017-01-23 15:39:41 +08:00
$ npm run dev --debug
2017-01-23 01:12:24 +08:00
Or
$ npm start --debug
```
支持Node.js原生调试功能: https://nodejs.org/api/debugger.html
2017-01-23 15:39:41 +08:00
开发环境部署
------------
2017-01-23 01:12:24 +08:00
生成node直接可以执行的代码到dist目录:
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$ npm run build
```
```
$ npm run production # 生产模式运行
Or
$ node dist/app.js
```
### PM2部署说明
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
提供了PM2部署RESTful API Server的示例配置, 位于“pm2.js”文件中。
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$ pm2 start pm2.js
```
2017-01-23 15:39:41 +08:00
PM2配合Docker部署说明: http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/
2017-01-23 01:12:24 +08:00
### Docker部署说明
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$ docker pull node
2017-01-23 04:59:10 +08:00
$ docker run -itd --name RESTfulAPI -v `pwd` :/usr/src/app -w /usr/src/app node node ./dist/app.js
2017-01-23 01:12:24 +08:00
```
2017-01-23 03:38:59 +08:00
通过'docker ps'查看是否运行成功及运行状态
2017-01-23 01:12:24 +08:00
### Linux/Mac 直接后台运行生产环境代码
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
有时候为了简单,我们也这样做:
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$ nohup node ./dist/app.js > logs/out.log &
```
2017-01-23 03:38:59 +08:00
查看运行状态(如果有'node app.js'出现则说明正在后台运行):
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$ ps aux|grep app.js
```
查看运行日志
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$ cat logs/out.log
```
监控运行状态
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$ tail -f logs/out.log
```
### 配合Vue-cli部署说明
2017-01-23 15:39:41 +08:00
2017-01-23 03:38:59 +08:00
Vue-cli( Vue2) 运行'npm run build'后会在'dist'目录中生成所有静态资源文件。推荐使用Nginx处理静态资源以达最佳利用效果, 然后通过上述任意一种方法部署RESTful API服务器。前后端是完全分离的, 请注意Koa2 RESTful API Server项目中config/main.json里面的跨域配置。
2017-01-23 01:12:24 +08:00
推荐的Nginx配置文件:
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
server
{
listen 80;
listen [::]:80;
server_name abc.com www.abc.com; #绑定域名
index index.html index.htm;
root /www/app/dist; #Vue -cli编译后的dist目录
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 12h;
}
location ~ /\.
{
deny all;
}
access_log off; #访问日志路径
}
```
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
Docker中Nginx运行命令(将上述配置文件任意命名放置于nginx_config目录中即可):
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$ docker run -itd -p 80:80 -p 443:443 -v `pwd` /nginx_config:/etc/nginx/conf.d nginx
```
2017-01-23 15:39:41 +08:00
引入插件介绍
------------
2017-01-23 01:12:24 +08:00
> 引入插件的版本将会持续更新
引入的插件:
2017-01-24 23:19:44 +08:00
`koa@2 koa-body@2 koa-router@next koa-session2 koa-static2 koa-compose require-directory babel-cli babel-register babel-plugin-transform-runtime babel-preset-es2015 babel-preset-stage-2 gulp gulp-eslint eslint eslint-config-standard eslint-friendly-formatter eslint-plugin-html eslint-plugin-promise nodemailer promise-mysql`
2017-01-23 03:38:59 +08:00
**koa2**: HTTP框架
2017-01-23 01:12:24 +08:00
Synopsis: HTTP framework.
2017-01-23 15:39:41 +08:00
From: https://github.com/koajs/koa v2
2017-01-23 03:38:59 +08:00
2017-01-23 04:59:10 +08:00
**koa-body**: body解析器
Synopsis: A full-feature koa body parser middleware.
2017-01-23 15:39:41 +08:00
From: https://github.com/dlau/koa-body
2017-01-23 03:38:59 +08:00
**koa-router**: Koa路由
Synopsis: Router middleware for koa.
2017-01-23 15:39:41 +08:00
From: https://github.com/alexmingoia/koa-router/tree/master/
2017-01-23 03:38:59 +08:00
**koa-session2**: Session中间件
Synopsis: Middleware for Koa2 to get/set session.
2017-01-23 15:39:41 +08:00
From: https://github.com/Secbone/koa-session2
2017-01-23 03:38:59 +08:00
**koa-static2**: 静态资源中间件
Synopsis: Middleware for Koa2 to serve a folder under a name declared by user.
2017-01-23 15:39:41 +08:00
From: https://github.com/Secbone/koa-static2
2017-01-23 03:38:59 +08:00
**koa-compose**: 多个中间件组合成一个
Synopsis: Compose several middleware into one.
2017-01-23 15:39:41 +08:00
From: https://github.com/koajs/compose
2017-01-23 04:59:10 +08:00
2017-01-23 03:38:59 +08:00
**require-directory**: 递归遍历指定目录
Synopsis: Recursively iterates over specified directory.
2017-01-23 15:39:41 +08:00
From: https://github.com/troygoode/node-require-directory
2017-01-23 01:12:24 +08:00
**babel-cli**: Babel编译ES6代码为ES5代码
Synopsis: Babel is a JavaScript compiler, ES6 to ES5.
From: https://github.com/babel/babel/tree/master/packages/babel-cli
**babel-register**: Babel开发环境实时编译ES6代码
Synopsis: Babel hook.
From: https://github.com/babel/babel/tree/master/packages/babel-cli
**babel-plugin-transform-runtime**: Babel配置ES6的依赖项
**babel-preset-es2015**: 同上
2017-01-23 15:39:41 +08:00
**babel-preset-stage-2**: 同上
2017-01-23 01:12:24 +08:00
**gulp**: 基于流的自动化构建工具
Synopsis: Gulp is a toolkit for automating painful or time-consuming tasks.
From: https://github.com/gulpjs/gulp
**gulp-eslint**: gulp的ESLint检查插件
Synopsis: A gulp plugin for ESLint.
From: https://github.com/adametry/gulp-eslint
**gulp-nodemon**: 修改JS代码后自动重启
Synopsis: nodemon will watch the files in the directory in which nodemon was started, and if any files change, nodemon will automatically restart your node application.
2017-01-23 15:39:41 +08:00
From: https://github.com/remy/nodemon
2017-01-23 01:12:24 +08:00
**eslint**: JavaScript语法检查工具
Synopsis: A fully pluggable tool for identifying and reporting on patterns in JavaScript.
From:
2017-01-23 15:39:41 +08:00
**eslint-config-standard**: 一个ESlint配置 Synopsis: ESLint Shareable Config for JavaScript Standard Style.
2017-01-23 01:12:24 +08:00
From: https://github.com/feross/eslint-config-standard
**eslint-friendly-formatter**: 使得ESlint提示在Sublime Text或iterm2中更友好, Atom也有对应的ESlint插件。
2017-01-23 03:38:59 +08:00
Synopsis: A simple formatter/reporter for ESLint that's friendly with Sublime Text and iterm2 'click to open file' functionality
2017-01-23 01:12:24 +08:00
From: https://github.com/royriojas/eslint-friendly-formatter
**eslint-plugin-html**: 检查HTML文件中的JS代码规范
Synopsis: An ESLint plugin to extract and lint scripts from HTML files.
From: https://github.com/BenoitZugmeyer/eslint-plugin-html
**eslint-plugin-promise**: 检查JavaScript promises
2017-01-23 15:39:41 +08:00
Synopsis: Enforce best practices for JavaScript promises. From: https://github.com/xjamundx/eslint-plugin-promise
2017-01-23 01:12:24 +08:00
**eslint-plugin-promise**: ESlint依赖项
2017-01-23 15:39:41 +08:00
Synopsis: ESlint Rules for the Standard Linter. From: https://github.com/xjamundx/eslint-plugin-standard
2017-01-23 03:38:59 +08:00
**nodemailer**: 发送邮件
Synopsis: Send e-mails with Node.JS.
From: https://github.com/nodemailer/nodemailer
**promise-mysql**: 操作MySQL数据库依赖
Synopsis: Promise Mysql.
2017-01-23 15:39:41 +08:00
From: https://github.com/lukeb-uk/node-promise-mysql
2017-01-23 04:59:10 +08:00
**sequelize**: 关系型数据库ORM
Synopsis: Sequelize is a promise-based ORM for Node.js.
From: https://github.com/sequelize/sequelize
**mysql**: MySQL库
Synopsis: A pure node.js JavaScript Client implementing the MySql protocol.
From: https://github.com/mysqljs/mysql
2017-01-23 01:12:24 +08:00
2017-01-23 15:39:41 +08:00
支持Koa2的中间件列表: https://github.com/koajs/koa/wiki
2017-01-23 01:12:24 +08:00
2017-01-23 15:39:41 +08:00
**其它经常配合Koa2的插件: **
2017-01-23 03:38:59 +08:00
2017-01-23 01:12:24 +08:00
**koa-nunjucks-2**:
2017-01-23 03:38:59 +08:00
一个好用的模版引擎, 可用于前后端, nunjucks: https://github.com/mozilla/nunjucks
**koa-favicon**:
2017-01-23 15:39:41 +08:00
Koa的favicon中间件: https://github.com/koajs/favicon
2017-01-23 03:38:59 +08:00
**koa-server-push**:
2017-01-23 15:39:41 +08:00
HTTP2推送中间件: https://github.com/silenceisgolden/koa-server-push
2017-01-23 03:38:59 +08:00
**koa-convert**: 转换旧的中间件支持Koa2
Synopsis: Convert koa generator-based middleware to promise-based middleware.
2017-01-23 15:39:41 +08:00
From: https://github.com/koajs/convert
2017-01-23 03:38:59 +08:00
**koa-logger**: 请求日志输出,需要配合上面的插件使用
Synopsis: Development style logger middleware for Koa.
From: https://github.com/koajs/logger
2017-01-23 01:12:24 +08:00
2017-01-23 04:59:10 +08:00
**koa-onerror**:
2017-01-23 15:39:41 +08:00
Koa的错误拦截中间件, 需要配合上面的插件使用: https://github.com/koajs/onerror
2017-01-23 04:59:10 +08:00
2017-01-24 23:19:44 +08:00
**koa-multer**: 处理数据中间件
Synopsis: Multer is a node.js middleware for handling multipart/form-data for koa.
From: https://github.com/koa-modules/multer
2017-01-23 15:39:41 +08:00
目录结构说明
------------
2017-01-23 01:12:24 +08:00
```bash
.
├── README.md
├── .babelrc # Babel 配置文件
├── .editorconfig # 编辑器风格定义文件
├── .eslintignore # ESlint 忽略文件列表
├── .eslintrc.js # ESlint 配置文件
├── .gitignore # Git 忽略文件列表
├── gulpfile.js # Gulp配置文件
├── package.json # 描述文件
├── pm2.js # pm2 部署示例文件
├── build # build 入口目录
│ └── dev-server.js # 开发环境 Babel 实时编译入口
├── src # 源代码目录,编译后目标源代码位于 dist 目录
2017-01-23 03:38:59 +08:00
│ ├── app.js # 入口文件
2017-01-23 15:39:41 +08:00
│ ├── config.js # 主配置文件(*谨防泄密!)
2017-01-23 03:38:59 +08:00
│ ├── plugin # 插件目录
│ └── smtp_sendemail # 示例插件 - 发邮件
│ ├── tool # 工具目录
│ ├── PluginLoader.js # 插件引入工具
│ └── Common.js # 示例插件 - 发邮件
│ ├── lib # 库目录
2017-01-23 01:12:24 +08:00
│ ├── controllers # 控制器
│ ├── models # 模型
│ ├── routes # 路由
2017-01-23 03:38:59 +08:00
│ └── services # 服务
├── assets # 静态资源目录
2017-01-23 01:12:24 +08:00
└── logs # 日志目录
```
2017-01-23 15:39:41 +08:00
各类主流框架调用RESTful API的示例代码( 仅供参考)
-------------------------------------------------
2017-01-23 01:12:24 +08:00
### AngularJS (Ionic同)
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$http({
2017-01-23 03:38:59 +08:00
method: 'post',
url: 'http://localhost:3000/xxx',
data: {para1:'para1',para2:'para2'},
2017-01-23 01:12:24 +08:00
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function (data) {
}).error(function (data) {
2017-01-23 03:38:59 +08:00
})
2017-01-23 15:39:41 +08:00
```
2017-01-23 01:12:24 +08:00
### jQuery
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
$.ajax({
cache: false,
type: 'POST',
2017-01-23 03:38:59 +08:00
url: 'http://localhost:3000/xxx',
2017-01-23 01:12:24 +08:00
data: {
para1: para1
},
async: false,
2017-01-23 03:38:59 +08:00
dataType: 'json',
2017-01-23 01:12:24 +08:00
success: function (result) {
},
error: function (err) {
2017-01-23 03:38:59 +08:00
console.log(err)
2017-01-23 01:12:24 +08:00
}
2017-01-23 03:38:59 +08:00
})
2017-01-23 01:12:24 +08:00
// 上传文件
//创建FormData对象
2017-01-23 03:38:59 +08:00
var data = new FormData()
2017-01-23 01:12:24 +08:00
//为FormData对象添加数据
//
$.each($('#inputfile')[0].files, function (i, file) {
2017-01-23 03:38:59 +08:00
data.append('upload_file', file)
})
2017-01-23 01:12:24 +08:00
$.ajax({
url: 'http://127.0.0.1:3000/api/upload_oss_img_demo',
type: 'POST',
data: data,
cache: false,
contentType: false, //不可缺
processData: false, //不可缺
success: function (data) {
2017-01-23 03:38:59 +08:00
console.log(data)
if (data.result == 'ok') {
$('#zzzz').attr('src', data.img_url)
2017-01-23 01:12:24 +08:00
}
}
2017-01-23 03:38:59 +08:00
})
2017-01-23 01:12:24 +08:00
```
### MUI
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
2017-01-23 03:38:59 +08:00
mui.ajax({ url: 'http://localhost:3000/xxx', dataType: 'json',
2017-01-23 01:12:24 +08:00
success: function(data){
},
error: function(data){
2017-01-23 03:38:59 +08:00
console.log('error!')
2017-01-23 01:12:24 +08:00
}
2017-01-23 03:38:59 +08:00
})
2017-01-23 01:12:24 +08:00
```
### JavaScript
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
var xhr = new XMLHttpRequest()
2017-01-23 03:38:59 +08:00
xhr.open('POST', 'http://localhost:3000/xxx', true) //POST或GET, true( 异步) 或 false( 同步)
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
2017-01-23 01:12:24 +08:00
xhr.withCredentials = true
xhr.onreadystatechange = function () {
if (obj.readyState == 4 & & obj.status == 200 || obj.status == 304) {
var gotServices = JSON.parse(xhr.responseText)
}else{
2017-01-23 03:38:59 +08:00
console.log('ajax失败了')
2017-01-23 01:12:24 +08:00
}
}
xhr.send({para1: para1})
```
### vue-resource
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
https://github.com/pagekit/vue-resource
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
// global Vue object
Vue.http.post('/someUrl', [body], {
2017-01-23 03:38:59 +08:00
headers: {'Content-type', 'application/x-www-form-urlencoded'}
}).then(successCallback, errorCallback)
2017-01-23 01:12:24 +08:00
```
### fetch
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
https://github.com/github/fetch
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
fetch('/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Hubot',
login: 'hubot',
})
}).then(function(response) {
// response.text()
}).then(function(body) {
// body
})
// 文件上传
2017-01-23 03:38:59 +08:00
var input = document.querySelector('input[type='file']')
2017-01-23 01:12:24 +08:00
var data = new FormData()
data.append('file', input.files[0])
data.append('user', 'hubot')
fetch('/avatars', {
method: 'POST',
body: data
})
```
### superagent
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
https://github.com/visionmedia/superagent
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
request.post('/user')
.set('Content-Type', 'application/json')
2017-01-23 03:38:59 +08:00
.send('{'name':'tj','pet':'tobi'}')
2017-01-23 01:12:24 +08:00
.end(callback)
```
2017-02-03 13:46:11 +08:00
### request
https://github.com/request/request
```
request.post('/api').form({key:'value'}), function(err,httpResponse,body){ /* ... */ })
```
2017-01-23 01:12:24 +08:00
在React中可以将上述任意方法其置于componentDidMount()中, Vue.js同理。
2017-01-23 15:39:41 +08:00
彻底移除ESlint方法
------------------
2017-01-23 01:12:24 +08:00
删除package.json的devDependencies中所有eslint开头的插件, 根目录下的“.eslintignore、.eslintrc.js”文件, 并且修改package.json的dev为:
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
```
2017-01-23 03:38:59 +08:00
'dev': 'gulp start'
2017-01-23 01:12:24 +08:00
```
2017-01-23 15:39:41 +08:00
2017-01-23 01:12:24 +08:00
删除gulpfile.js中的lint、eslint_start两个任务, 并且把default改为“gulp.task('default', ['start']”。
2017-02-07 16:05:12 +08:00
2017-02-12 01:28:00 +08:00
更新说明
--------
2017-03-01 23:05:39 +08:00
2017-03-27 17:28:08 +08:00
*v0.0.9 2017年03月27日17:25:58*
1. 修改了`src/controllers/upload.js`文件,添加了上传文件示例代码。
2. 修复了`src/lib/mysql.js`引用路径错误的BUG。
3. 修改了`src/controllers/api.js`GET参数获取的示例。
2017-03-01 23:05:39 +08:00
*v0.0.8 2017年03月01日23:03:44*
1、在src/app.js 18行 后添加了
2017-03-27 17:28:08 +08:00
2017-03-01 23:05:39 +08:00
```
jsonLimit: '20mb',
formLimit: '10mb',
textLimit: '20mb',
```
2017-03-27 17:28:08 +08:00
2017-03-01 23:05:39 +08:00
以免表单过长导致提交失败。
2017-02-18 19:02:15 +08:00
*v0.0.7 2017年02月18日19:01:48*
2017-03-27 17:28:08 +08:00
1、修改了index.js、config.js( 详情请看github记录) , 完善了对跨域的处理。 更新建议: 对应github修改记录同步修改, 方便将来部署调试。
2017-02-18 19:02:15 +08:00
2017-02-17 21:18:58 +08:00
*v0.0.6 2017年02月17日21:17:23*
1、修改了src/lib/sequelize.js文件,添加了对utf8mb4的支持( 要求MySQL版本>5.5)。
2017-02-12 01:28:00 +08:00
*v0.0.5 2017年02月12日01:25:34*
1、修改了gulpfile.js文件, 在更改文件热重启的时候无需检查全部文件, 仅检查改动文件, 开发速度更快。
2、修改了package.json中"start"项的值为"gulp nodemon"配合gulpfile.js文件的修改。
2017-02-07 16:05:12 +08:00
*v0.0.4 2017年02月07日15:57:17*
1、修改了部分配置文件的配置方法, 使之更为规范( 老版本用户无须理会, 对程序没有影响) 。
2、修改了eslintrc.js文件中的JavaScript版本配置, 改为ES8, 兼容async、await。
2017-02-12 01:28:00 +08:00
3、修改gulpfile.js文件第12行, 检查`src/**/*.js`文件。