1.0.2
This commit is contained in:
parent
a6fd705801
commit
118b8f9d3a
415
README.md
415
README.md
@ -1,82 +1,76 @@
|
||||
Koa2 RESTful API 服务器脚手架
|
||||
=============================
|
||||
# Koa2 RESTful API 服务器脚手架
|
||||
|
||||
这是一个基于Koa2的轻量级RESTful API Server脚手架,支持ES6。
|
||||
这是一个基于 Koa2 的轻量级 RESTful API Server 脚手架,支持 ES6。
|
||||
|
||||
**注意:**因升级Koa版本至2.3.0+,为配合相应的依赖项,故需要Node.js版本大于等于v8.0.0(建议v11.13.0),NPM大于等于v5.0.0。建议使用yarn代替npm。
|
||||
**注意:**因升级 Koa 版本至 2.3.0+,为配合相应的依赖项,故需要 Node.js 版本大于等于 v8.0.0(建议 v11.13.0),NPM 大于等于 v5.0.0。建议使用 yarn 代替 npm。
|
||||
|
||||
约定使用JSON格式传输数据,POST、PUT、DELET方法支持的Content-Type为`application/x-www-form-urlencoded、multipart/form-data、application/json`可配置支持跨域。非上传文件推荐application/x-www-form-urlencoded。通常情况下返回application/json格式的JSON数据。
|
||||
约定使用 JSON 格式传输数据,POST、PUT、DELET 方法支持的 Content-Type 为`application/x-www-form-urlencoded、multipart/form-data、application/json`可配置支持跨域。非上传文件推荐 application/x-www-form-urlencoded。通常情况下返回 application/json 格式的 JSON 数据。
|
||||
|
||||
可选用redis等非关系型数据库。考虑RESTful API Server的实际开发需要,这里通过sequelize.js作为PostgreSQL, MySQL, MariaDB, SQLite, MSSQL关系型数据库的ORM,如无需关系型ORM,`npm remove sequelize -S`,然后删除`src/lib/sequelize.js`文件。
|
||||
可选用 redis 等非关系型数据库。考虑 RESTful API Server 的实际开发需要,这里通过 sequelize.js 作为 PostgreSQL, MySQL, MariaDB, SQLite, MSSQL 关系型数据库的 ORM,如无需关系型 ORM,`npm remove sequelize -S`,然后删除`src/lib/sequelize.js`文件。
|
||||
|
||||
此脚手架只安装了一些和Koa2不冲突的搭建RESTful API Server的必要插件,附带每一个插件的说明。采用ESlint进行语法检查。
|
||||
此脚手架只安装了一些和 Koa2 不冲突的搭建 RESTful API Server 的必要插件,附带每一个插件的说明。采用 ESlint 进行语法检查。
|
||||
|
||||
因此脚手架主要提供RESTful API,故暂时不考虑前端静态资源处理,只提供静态资源访问的基本方法便于访问用户上传到服务器的图片等资源。基本目录结构与vue-cli保持一致,可配合React、AngularJS、Vue.js等前端框架使用。在Cordova/PhoneGap、Electron中使用时需要开启跨域功能。
|
||||
因此脚手架主要提供 RESTful API,故暂时不考虑前端静态资源处理,只提供静态资源访问的基本方法便于访问用户上传到服务器的图片等资源。基本目录结构与 vue-cli 保持一致,可配合 React、AngularJS、Vue.js 等前端框架使用。在 Cordova/PhoneGap、Electron 中使用时需要开启跨域功能。
|
||||
|
||||
**免责声明:** 此脚手架仅为方便开发提供基础环境,任何人或组织均可随意克隆使用,使用引入的框架需遵循原作者规定的相关协议(部分框架列表及来源地址在下方)。采用此脚手架产生的任何后果请自行承担,本人不对此脚手架负任何法律责任,使用即代表同意此条。
|
||||
**免责声明:** 此脚手架仅为方便开发提供基础环境,任何人或组织均可随意克隆使用,使用引入的框架需遵循原作者规定的相关协议(部分框架列表及来源地址在下方)。项目维护者均不对采用此脚手架产生的任何后果负责。
|
||||
|
||||
目前暂未加入软件测试模块,下一个版本会加入该功能并提供集成方案。建议自行集成jest。
|
||||
**基于 Vue 2,Webpack 4,Koa 2 的 SSR 脚手架:**[https://github.com/yi-ge/Vue-SSR-Koa2-Scaffold](https://github.com/yi-ge/Vue-SSR-Koa2-Scaffold)。
|
||||
|
||||
**基于Vue 2,Webpack 4,Koa 2的SSR脚手架:**[https://github.com/yi-ge/Vue-SSR-Koa2-Scaffold](https://github.com/yi-ge/Vue-SSR-Koa2-Scaffold)。
|
||||
|
||||
开发使用说明
|
||||
------------
|
||||
## 开发使用说明
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/yi-ge/koa2-API-scaffold.git
|
||||
git clone https://github.com/yi-ge/koa2-API-scaffold.git
|
||||
|
||||
$ cd mv koa2-API-scaffold
|
||||
$ npm install
|
||||
$ npm run dev # 可执行npm start跳过ESlint检查。
|
||||
cd mv koa2-API-scaffold
|
||||
npm install
|
||||
npm run dev # 可执行npm start跳过ESlint检查。
|
||||
```
|
||||
|
||||
访问: http://127.0.0.1:3000/
|
||||
|
||||
调试说明
|
||||
--------
|
||||
## 调试说明
|
||||
|
||||
```
|
||||
$ npm run dev --debug
|
||||
```bash
|
||||
npm run dev --debug
|
||||
|
||||
Or
|
||||
|
||||
$ npm start --debug
|
||||
npm start --debug
|
||||
```
|
||||
|
||||
支持Node.js原生调试功能:https://nodejs.org/api/debugger.html
|
||||
支持 Node.js 原生调试功能:https://nodejs.org/api/debugger.html
|
||||
|
||||
开发环境部署
|
||||
------------
|
||||
## 开发环境部署
|
||||
|
||||
生成node直接可以执行的代码到dist目录:
|
||||
生成 node 直接可以执行的代码到 dist 目录:
|
||||
|
||||
```
|
||||
$ npm run build
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
```
|
||||
$ npm run production # 生产模式运行
|
||||
```bash
|
||||
npm run production # 生产模式运行
|
||||
|
||||
Or
|
||||
# Or
|
||||
|
||||
$ node dist/app.js
|
||||
node dist/app.js
|
||||
```
|
||||
|
||||
### PM2部署说明
|
||||
### PM2 部署说明
|
||||
|
||||
提供了PM2部署RESTful API Server的示例配置,位于“pm2.js”文件中。
|
||||
提供了 PM2 部署 RESTful API Server 的示例配置,位于“pm2.js”文件中。
|
||||
|
||||
```
|
||||
$ pm2 start pm2.js
|
||||
```bash
|
||||
pm2 start pm2.js
|
||||
```
|
||||
|
||||
PM2配合Docker部署说明: http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/
|
||||
PM2 配合 Docker 部署说明: http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/
|
||||
|
||||
### Docker部署说明
|
||||
### Docker 部署说明
|
||||
|
||||
```
|
||||
$ docker pull node
|
||||
$ docker run -itd --name RESTfulAPI -v `pwd`:/usr/src/app -w /usr/src/app node node ./dist/app.js
|
||||
```bash
|
||||
docker pull node
|
||||
docker run -itd --name RESTfulAPI -v `pwd`:/usr/src/app -w /usr/src/app node node ./dist/app.js
|
||||
```
|
||||
|
||||
通过'docker ps'查看是否运行成功及运行状态
|
||||
@ -85,35 +79,35 @@ $ docker run -itd --name RESTfulAPI -v `pwd`:/usr/src/app -w /usr/src/app node n
|
||||
|
||||
有时候为了简单,我们也这样做:
|
||||
|
||||
```
|
||||
$ nohup node ./dist/app.js > logs/out.log &
|
||||
```bash
|
||||
nohup node ./dist/app.js > logs/out.log &
|
||||
```
|
||||
|
||||
查看运行状态(如果有'node app.js'出现则说明正在后台运行):
|
||||
|
||||
```
|
||||
$ ps aux|grep app.js
|
||||
```bash
|
||||
ps aux|grep app.js
|
||||
```
|
||||
|
||||
查看运行日志
|
||||
|
||||
```
|
||||
$ cat logs/out.log
|
||||
```bash
|
||||
cat logs/out.log
|
||||
```
|
||||
|
||||
监控运行状态
|
||||
|
||||
```
|
||||
$ tail -f logs/out.log
|
||||
```bash
|
||||
tail -f logs/out.log
|
||||
```
|
||||
|
||||
### 配合Vue-cli部署说明
|
||||
### 配合 Vue-cli 部署说明
|
||||
|
||||
Vue-cli(Vue2)运行'npm run build'后会在'dist'目录中生成所有静态资源文件。推荐使用Nginx处理静态资源以达最佳利用效果,然后通过上述任意一种方法部署RESTful API服务器。前后端是完全分离的,请注意Koa2 RESTful API Server项目中config/main.json里面的跨域配置。
|
||||
Vue-cli(Vue2)运行'npm run build'后会在'dist'目录中生成所有静态资源文件。推荐使用 Nginx 处理静态资源以达最佳利用效果,然后通过上述任意一种方法部署 RESTful API 服务器。前后端是完全分离的,请注意 Koa2 RESTful API Server 项目中 config/main.json 里面的跨域配置。
|
||||
|
||||
推荐的Nginx配置文件:
|
||||
推荐的 Nginx 配置文件:
|
||||
|
||||
```
|
||||
```text
|
||||
server
|
||||
{
|
||||
listen 80;
|
||||
@ -141,33 +135,35 @@ server
|
||||
}
|
||||
```
|
||||
|
||||
Docker中Nginx运行命令(将上述配置文件任意命名放置于nginx_config目录中即可):
|
||||
Docker 中 Nginx 运行命令(将上述配置文件任意命名放置于 nginx_config 目录中即可):
|
||||
|
||||
```
|
||||
$ docker run -itd -p 80:80 -p 443:443 -v `pwd`/nginx_config:/etc/nginx/conf.d nginx
|
||||
```bash
|
||||
docker run -itd -p 80:80 -p 443:443 -v `pwd`/nginx_config:/etc/nginx/conf.d nginx
|
||||
```
|
||||
|
||||
### 关于Token使用的特别说明(JWT身份认证)
|
||||
### 关于 Token 使用的特别说明(JWT 身份认证)
|
||||
|
||||
`src\app.js`目录中有一行代码:
|
||||
```.use(jwt({ secret: publicKey }).unless({ path: [/^\/public|\/user\/login|\/assets/] }))```
|
||||
`.use(jwt({ secret: publicKey }).unless({ path: [/^\/public|\/user\/login|\/assets/] }))`
|
||||
|
||||
在path里面的开头路径则不进行身份认证,否则都将进行鉴权。
|
||||
在 path 里面的开头路径则不进行身份认证,否则都将进行 鉴权。
|
||||
|
||||
前端处理方案:
|
||||
```
|
||||
import axios from "axios"
|
||||
import { getToken } from "./tool"
|
||||
|
||||
const DevBaseUrl = "http://127.0.0.1:8080"
|
||||
const ProdBashUrl = "https://xxx.xxx"
|
||||
```javascript
|
||||
import axios from 'axios'
|
||||
import { getToken } from './tool'
|
||||
|
||||
const DevBaseUrl = 'http://127.0.0.1:8080'
|
||||
const ProdBashUrl = 'https://xxx.xxx'
|
||||
|
||||
let config = {
|
||||
baseURL: process.env.NODE_ENV !== "production" ? DevBaseUrl : ProdBashUrl // 配置API接口地址
|
||||
baseURL: process.env.NODE_ENV !== 'production' ? DevBaseUrl : ProdBashUrl // 配置API接口地址
|
||||
}
|
||||
|
||||
let token = getToken()
|
||||
if (token) {
|
||||
config.headers = { Authorization: "Bearer " + token }
|
||||
config.headers = { Authorization: 'Bearer ' + token }
|
||||
}
|
||||
|
||||
let request = axios.create(config)
|
||||
@ -196,109 +192,107 @@ export default request
|
||||
```
|
||||
|
||||
`tool.js`文件
|
||||
```
|
||||
|
||||
```javascript
|
||||
// 写 cookies
|
||||
export let setCookie = function setCookie(name, value, time) {
|
||||
if (time) {
|
||||
let strsec = getsec(time);
|
||||
let exp = new Date();
|
||||
exp.setTime(exp.getTime() + parseInt(strsec));
|
||||
document.cookie = name +
|
||||
"=" +
|
||||
escape(value) +
|
||||
";expires=" +
|
||||
exp.toGMTString();
|
||||
let strsec = getsec(time)
|
||||
let exp = new Date()
|
||||
exp.setTime(exp.getTime() + parseInt(strsec))
|
||||
document.cookie =
|
||||
name + '=' + escape(value) + ';expires=' + exp.toGMTString()
|
||||
} else {
|
||||
document.cookie = name + "=" + escape(value);
|
||||
document.cookie = name + '=' + escape(value)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 读 cookies
|
||||
export let getCookie = function(name) {
|
||||
let reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
|
||||
let arr = document.cookie.match(reg);
|
||||
return arr ? unescape(arr[2]) : null;
|
||||
};
|
||||
let reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
|
||||
let arr = document.cookie.match(reg)
|
||||
return arr ? unescape(arr[2]) : null
|
||||
}
|
||||
|
||||
// 删 cookies
|
||||
export let delCookie = function(name) {
|
||||
var exp = new Date();
|
||||
exp.setTime(exp.getTime() - 1);
|
||||
var cval = getCookie(name);
|
||||
var exp = new Date()
|
||||
exp.setTime(exp.getTime() - 1)
|
||||
var cval = getCookie(name)
|
||||
if (cval != null) {
|
||||
document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
|
||||
document.cookie = name + '=' + cval + ';expires=' + exp.toGMTString()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 获取Token
|
||||
export let getToken = function() {
|
||||
if (window.sessionStorage && window.sessionStorage.Bearer) {
|
||||
return window.sessionStorage.Bearer;
|
||||
return window.sessionStorage.Bearer
|
||||
} else if (window.localStorage && window.localStorage.Bearer) {
|
||||
return window.localStorage.Bearer;
|
||||
return window.localStorage.Bearer
|
||||
} else if (window.document.cookie) {
|
||||
return getCookie("Bearer");
|
||||
return getCookie('Bearer')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 设置Token
|
||||
export let setToken = function(token, rememberTime) {
|
||||
if (window.sessionStorage) {
|
||||
window.sessionStorage.Bearer = token;
|
||||
window.sessionStorage.Bearer = token
|
||||
}
|
||||
|
||||
if ((rememberTime && window.localStorage) || !window.sessionStorage) {
|
||||
window.localStorage.Bearer = token;
|
||||
window.localStorage.Bearer = token
|
||||
}
|
||||
|
||||
if (
|
||||
window.document.cookie && !window.sessionStorage && !window.localStorage
|
||||
window.document.cookie &&
|
||||
!window.sessionStorage &&
|
||||
!window.localStorage
|
||||
) {
|
||||
if (rememberTime) {
|
||||
setCookie("Bearer", token, rememberTime);
|
||||
setCookie('Bearer', token, rememberTime)
|
||||
} else {
|
||||
setCookie("Bearer", token);
|
||||
setCookie('Bearer', token)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 删除Token
|
||||
export let delToken = function() {
|
||||
if (window.sessionStorage && window.sessionStorage.Bearer) {
|
||||
window.sessionStorage.removeItem("Bearer");
|
||||
window.sessionStorage.removeItem('Bearer')
|
||||
}
|
||||
|
||||
if (window.localStorage && window.localStorage.Bearer) {
|
||||
window.localStorage.removeItem("Bearer");
|
||||
window.localStorage.removeItem('Bearer')
|
||||
}
|
||||
|
||||
if (window.document.cookie) {
|
||||
delCookie("Bearer");
|
||||
delCookie('Bearer')
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
大概原理:
|
||||
通过某个API(通常是登录API)获取成功后的Token,存于本地,然后每次请求的时候在Header带上`Authorization: "Bearer " + token`,通常情况下无需担心本地Token被破解。
|
||||
通过某个 API(通常是登录 API)获取成功后的 Token,存于本地,然后每次请求的时候在 Header 带上`Authorization: "Bearer " + token`,通常情况下无需担心本地 Token 被破解。
|
||||
|
||||
引入插件介绍
|
||||
------------
|
||||
## 引入插件介绍
|
||||
|
||||
> 引入插件的版本将会持续更新
|
||||
|
||||
引入的插件:
|
||||
`koa@2 koa-body@2 koa-router@next 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 等`
|
||||
|
||||
**koa2**: HTTP框架
|
||||
**koa2**: HTTP 框架
|
||||
Synopsis: HTTP framework.
|
||||
From: https://github.com/koajs/koa v2
|
||||
|
||||
**koa-body**: body解析器
|
||||
**koa-body**: body 解析器
|
||||
Synopsis: A full-feature koa body parser middleware.
|
||||
From: https://github.com/dlau/koa-body
|
||||
|
||||
**koa-router**: Koa路由
|
||||
**koa-router**: Koa 路由
|
||||
Synopsis: Router middleware for koa.
|
||||
From: https://github.com/alexmingoia/koa-router/tree/master/
|
||||
|
||||
@ -314,15 +308,15 @@ export let delToken = function() {
|
||||
Synopsis: Recursively iterates over specified directory.
|
||||
From: https://github.com/troygoode/node-require-directory
|
||||
|
||||
**babel-cli**: Babel编译ES6代码为ES5代码
|
||||
**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代码
|
||||
**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-plugin-transform-runtime**: Babel 配置 ES6 的依赖项
|
||||
**babel-preset-es2015**: 同上
|
||||
**babel-preset-stage-2**: 同上
|
||||
|
||||
@ -330,56 +324,56 @@ export let delToken = function() {
|
||||
Synopsis: Gulp is a toolkit for automating painful or time-consuming tasks.
|
||||
From: https://github.com/gulpjs/gulp
|
||||
|
||||
**gulp-eslint**: gulp的ESLint检查插件
|
||||
**gulp-eslint**: gulp 的 ESLint 检查插件
|
||||
Synopsis: A gulp plugin for ESLint.
|
||||
From: https://github.com/adametry/gulp-eslint
|
||||
|
||||
**gulp-nodemon**: 修改JS代码后自动重启
|
||||
**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.
|
||||
From: https://github.com/remy/nodemon
|
||||
|
||||
**eslint**: JavaScript语法检查工具
|
||||
**eslint**: JavaScript 语法检查工具
|
||||
Synopsis: A fully pluggable tool for identifying and reporting on patterns in JavaScript.
|
||||
From:
|
||||
|
||||
**eslint-config-standard**: 一个ESlint配置 Synopsis: ESLint Shareable Config for JavaScript Standard Style.
|
||||
**eslint-config-standard**: 一个 ESlint 配置 Synopsis: ESLint Shareable Config for JavaScript Standard Style.
|
||||
From: https://github.com/feross/eslint-config-standard
|
||||
|
||||
**eslint-friendly-formatter**: 使得ESlint提示在Sublime Text或iterm2中更友好,Atom也有对应的ESlint插件。
|
||||
**eslint-friendly-formatter**: 使得 ESlint 提示在 Sublime Text 或 iterm2 中更友好,Atom 也有对应的 ESlint 插件。
|
||||
Synopsis: A simple formatter/reporter for ESLint that's friendly with Sublime Text and iterm2 'click to open file' functionality
|
||||
From: https://github.com/royriojas/eslint-friendly-formatter
|
||||
|
||||
**eslint-plugin-html**: 检查HTML文件中的JS代码规范
|
||||
**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
|
||||
**eslint-plugin-promise**: 检查 JavaScript promises
|
||||
Synopsis: Enforce best practices for JavaScript promises. From: https://github.com/xjamundx/eslint-plugin-promise
|
||||
|
||||
**eslint-plugin-promise**: ESlint依赖项
|
||||
**eslint-plugin-promise**: ESlint 依赖项
|
||||
Synopsis: ESlint Rules for the Standard Linter. From: https://github.com/xjamundx/eslint-plugin-standard
|
||||
|
||||
**nodemailer**: 发送邮件
|
||||
Synopsis: Send e-mails with Node.JS.
|
||||
From: https://github.com/nodemailer/nodemailer
|
||||
|
||||
**promise-mysql**: 操作MySQL数据库依赖
|
||||
**promise-mysql**: 操作 MySQL 数据库依赖
|
||||
Synopsis: Promise Mysql.
|
||||
From: https://github.com/lukeb-uk/node-promise-mysql
|
||||
|
||||
**sequelize**: 关系型数据库ORM
|
||||
**sequelize**: 关系型数据库 ORM
|
||||
Synopsis: Sequelize is a promise-based ORM for Node.js.
|
||||
From: https://github.com/sequelize/sequelize
|
||||
|
||||
**mysql**: MySQL库
|
||||
**mysql**: MySQL 库
|
||||
Synopsis: A pure node.js JavaScript Client implementing the MySql protocol.
|
||||
From: https://github.com/mysqljs/mysql
|
||||
|
||||
支持Koa2的中间件列表:https://github.com/koajs/koa/wiki
|
||||
支持 Koa2 的中间件列表:https://github.com/koajs/koa/wiki
|
||||
|
||||
**其它经常配合Koa2的插件:**
|
||||
**其它经常配合 Koa2 的插件:**
|
||||
|
||||
**koa-session2**: Session中间件
|
||||
**koa-session2**: Session 中间件
|
||||
Synopsis: Middleware for Koa2 to get/set session.
|
||||
From: https://github.com/Secbone/koa-session2
|
||||
|
||||
@ -387,12 +381,12 @@ export let delToken = function() {
|
||||
一个好用的模版引擎,可用于前后端,nunjucks:https://github.com/mozilla/nunjucks
|
||||
|
||||
**koa-favicon**:
|
||||
Koa的favicon中间件:https://github.com/koajs/favicon
|
||||
Koa 的 favicon 中间件:https://github.com/koajs/favicon
|
||||
|
||||
**koa-server-push**:
|
||||
HTTP2推送中间件:https://github.com/silenceisgolden/koa-server-push
|
||||
HTTP2 推送中间件:https://github.com/silenceisgolden/koa-server-push
|
||||
|
||||
**koa-convert**: 转换旧的中间件支持Koa2
|
||||
**koa-convert**: 转换旧的中间件支持 Koa2
|
||||
Synopsis: Convert koa generator-based middleware to promise-based middleware.
|
||||
From: https://github.com/koajs/convert
|
||||
|
||||
@ -401,14 +395,13 @@ HTTP2推送中间件:https://github.com/silenceisgolden/koa-server-push
|
||||
From: https://github.com/koajs/logger
|
||||
|
||||
**koa-onerror**:
|
||||
Koa的错误拦截中间件,需要配合上面的插件使用:https://github.com/koajs/onerror
|
||||
Koa 的错误拦截中间件,需要配合上面的插件使用:https://github.com/koajs/onerror
|
||||
|
||||
**koa-multer**: 处理数据中间件
|
||||
Synopsis: Multer is a node.js middleware for handling multipart/form-data for koa.
|
||||
From: https://github.com/koa-modules/multer
|
||||
|
||||
目录结构说明
|
||||
------------
|
||||
## 目录结构说明
|
||||
|
||||
```bash
|
||||
.
|
||||
@ -440,8 +433,7 @@ Koa的错误拦截中间件,需要配合上面的插件使用:https://github
|
||||
└── logs # 日志目录
|
||||
```
|
||||
|
||||
集成NUXT请求时身份认证说明
|
||||
--------------------------
|
||||
## 集成 NUXT 请求时身份认证说明
|
||||
|
||||
```
|
||||
import Vue from 'vue'
|
||||
@ -482,27 +474,30 @@ axios.interceptors.request.use(
|
||||
Vue.prototype.$request = request
|
||||
```
|
||||
|
||||
各类主流框架调用RESTful API的示例代码(仅供参考)
|
||||
-------------------------------------------------
|
||||
## 各类主流框架调用 RESTful API 的示例代码(仅供参考)
|
||||
|
||||
### AngularJS (Ionic同)
|
||||
### AngularJS (Ionic 同)
|
||||
|
||||
```
|
||||
```javascript
|
||||
$http({
|
||||
method: 'post',
|
||||
url: 'http://localhost:3000/xxx',
|
||||
data: {para1:'para1',para2:'para2'},
|
||||
data: { para1: 'para1', para2: 'para2' },
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}).success(function (data) {
|
||||
}).error(function (data) {
|
||||
})
|
||||
.success(function(data) {
|
||||
// do something
|
||||
})
|
||||
.error(function(data) {
|
||||
// do something
|
||||
})
|
||||
```
|
||||
|
||||
### jQuery
|
||||
|
||||
```
|
||||
```javascript
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: 'POST',
|
||||
@ -512,9 +507,8 @@ $.ajax({
|
||||
},
|
||||
async: false,
|
||||
dataType: 'json',
|
||||
success: function (result) {
|
||||
},
|
||||
error: function (err) {
|
||||
success: function(result) {},
|
||||
error: function(err) {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
@ -524,7 +518,7 @@ $.ajax({
|
||||
var data = new FormData()
|
||||
//为FormData对象添加数据
|
||||
//
|
||||
$.each($('#inputfile')[0].files, function (i, file) {
|
||||
$.each($('#inputfile')[0].files, function(i, file) {
|
||||
data.append('upload_file', file)
|
||||
})
|
||||
$.ajax({
|
||||
@ -534,24 +528,23 @@ $.ajax({
|
||||
cache: false,
|
||||
contentType: false, //不可缺
|
||||
processData: false, //不可缺
|
||||
success: function (data) {
|
||||
success: function(data) {
|
||||
console.log(data)
|
||||
if (data.result == 'ok') {
|
||||
$('#zzzz').attr('src', data.img_url)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### MUI
|
||||
|
||||
```
|
||||
mui.ajax({ url: 'http://localhost:3000/xxx', dataType: 'json',
|
||||
success: function(data){
|
||||
|
||||
},
|
||||
error: function(data){
|
||||
```javascript
|
||||
mui.ajax({
|
||||
url: 'http://localhost:3000/xxx',
|
||||
dataType: 'json',
|
||||
success: function(data) {},
|
||||
error: function(data) {
|
||||
console.log('error!')
|
||||
}
|
||||
})
|
||||
@ -559,26 +552,26 @@ mui.ajax({ url: 'http://localhost:3000/xxx', dataType: 'json',
|
||||
|
||||
### JavaScript
|
||||
|
||||
```
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.open('POST', 'http://localhost:3000/xxx', true) //POST或GET,true(异步)或 false(同步)
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
|
||||
xhr.withCredentials = true
|
||||
xhr.onreadystatechange = function () {
|
||||
if (obj.readyState == 4 && obj.status == 200 || obj.status == 304) {
|
||||
```javascript
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.open('POST', 'http://localhost:3000/xxx', true) //POST或GET,true(异步)或 false(同步)
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
|
||||
xhr.withCredentials = true
|
||||
xhr.onreadystatechange = function() {
|
||||
if ((obj.readyState == 4 && obj.status == 200) || obj.status == 304) {
|
||||
var gotServices = JSON.parse(xhr.responseText)
|
||||
}else{
|
||||
} else {
|
||||
console.log('ajax失败了')
|
||||
}
|
||||
}
|
||||
xhr.send({para1: para1})
|
||||
}
|
||||
xhr.send({ para1: para1 })
|
||||
```
|
||||
|
||||
### vue-resource
|
||||
|
||||
https://github.com/pagekit/vue-resource
|
||||
|
||||
```
|
||||
```javascript
|
||||
// global Vue object
|
||||
Vue.http.post('/someUrl', [body], {
|
||||
headers: {'Content-type', 'application/x-www-form-urlencoded'}
|
||||
@ -589,7 +582,7 @@ Vue.http.post('/someUrl', [body], {
|
||||
|
||||
https://github.com/github/fetch
|
||||
|
||||
```
|
||||
```javascript
|
||||
fetch('/users', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@ -622,7 +615,7 @@ fetch('/avatars', {
|
||||
|
||||
https://github.com/visionmedia/superagent
|
||||
|
||||
```
|
||||
```javascript
|
||||
request.post('/user')
|
||||
.set('Content-Type', 'application/json')
|
||||
.send('{'name':'tj','pet':'tobi'}')
|
||||
@ -633,69 +626,73 @@ request.post('/user')
|
||||
|
||||
https://github.com/request/request
|
||||
|
||||
```
|
||||
```javascript
|
||||
request.post('/api').form({key:'value'}), function(err,httpResponse,body){ /* ... */ })
|
||||
```
|
||||
|
||||
在React中可以将上述任意方法其置于componentDidMount()中,Vue.js同理。
|
||||
在 React 中可以将上述任意方法其置于 componentDidMount()中,Vue.js 同理。
|
||||
|
||||
彻底移除ESlint方法
|
||||
------------------
|
||||
## 彻底移除 ESlint 方法
|
||||
|
||||
删除package.json的devDependencies中所有eslint开头的插件,根目录下的“.eslintignore、.eslintrc.js”文件,并且修改package.json的dev为:
|
||||
删除 package.json 的 devDependencies 中所有 eslint 开头的插件,根目录下的“.eslintignore、.eslintrc.js”文件,并且修改 package.json 的 dev 为:
|
||||
|
||||
```
|
||||
```bash
|
||||
'dev': 'gulp start'
|
||||
```
|
||||
|
||||
删除gulpfile.js中的lint、eslint_start两个任务,并且把default改为“gulp.task('default', ['start']”。
|
||||
删除 gulpfile.js 中的 lint、eslint_start 两个任务,并且把 default 改为“gulp.task('default', ['start']”。
|
||||
|
||||
更新说明
|
||||
--------
|
||||
*v1.0.1 2019年06月02日21:54:00*
|
||||
## 更新说明
|
||||
|
||||
1. 添加Dockerfile
|
||||
_v1.0.2 2019 年 06 月 07 日 15:15:37_
|
||||
|
||||
*v1.0.0 2019年04月07日21:19:59*
|
||||
1. 解决`WS-2019-0064`警告,升级依赖项版本。
|
||||
2. 规范路由引入方式,增加不同写法的示例。
|
||||
|
||||
_v1.0.1 2019 年 06 月 02 日 21:54:00_
|
||||
|
||||
1. 添加 Dockerfile
|
||||
|
||||
_v1.0.0 2019 年 04 月 07 日 21:19:59_
|
||||
|
||||
1. 升级依赖项版本(node11.13.0)。
|
||||
2. 添加Jest。
|
||||
2. 添加 Jest。
|
||||
|
||||
*v0.2.6 2018年03月24日22:16:43*
|
||||
_v0.2.6 2018 年 03 月 24 日 22:16:43_
|
||||
|
||||
1. 升级依赖项版本(node9.9.0)。
|
||||
|
||||
*v0.2.5 2018年01月13日10:37:29*
|
||||
_v0.2.5 2018 年 01 月 13 日 10:37:29_
|
||||
|
||||
1. 升级依赖项版本(node9.3.0)。
|
||||
2. 添加了Token使用说明。
|
||||
2. 添加了 Token 使用说明。
|
||||
|
||||
*v0.2.4 2017年12月01日14:16:03*
|
||||
_v0.2.4 2017 年 12 月 01 日 14:16:03_
|
||||
|
||||
1. 升级依赖项版本(node9.2.0)。
|
||||
|
||||
*v0.2.3 2017年10月23日23:26:56*
|
||||
_v0.2.3 2017 年 10 月 23 日 23:26:56_
|
||||
|
||||
1. 升级依赖项版本(node8.7.0)。
|
||||
|
||||
*v0.2.2 2017年09月17日17:45:07*
|
||||
_v0.2.2 2017 年 09 月 17 日 17:45:07_
|
||||
|
||||
1. 升级依赖项版本(在node8.5.0测试)。
|
||||
1. 升级依赖项版本(在 node8.5.0 测试)。
|
||||
|
||||
*v0.2.1 2017年07月19日19:38:19*
|
||||
_v0.2.1 2017 年 07 月 19 日 19:38:19_
|
||||
|
||||
1. 移除MySQL模块(重复了)。
|
||||
1. 移除 MySQL 模块(重复了)。
|
||||
2. 添加更详细的说明。
|
||||
|
||||
*v0.2 2017年07月16日22:48:34*
|
||||
_v0.2 2017 年 07 月 16 日 22:48:34_
|
||||
|
||||
1. 升级koa为2.3.0版本。
|
||||
2. 将koa-session2替换为koa-jwt,添加了jsonwebtoken。
|
||||
1. 升级 koa 为 2.3.0 版本。
|
||||
2. 将 koa-session2 替换为 koa-jwt,添加了 jsonwebtoken。
|
||||
3. 升级了以下依赖的版本: koa@2.3.0, koa-body@2.3.0, koa-router@7.2.1, babel-cli@6.24.1, babel-preset-es2015@6.24.1, babel-preset-stage-2@6.24.1, babel-register@6.24.1, eslint-plugin-promise@3.5.0, koa-compose@4.0.0, nodemailer@4.0.1, sequelize@4.3.2, eslint@4.2.0, eslint-config-standard@10.2.1, eslint-friendly-formatter@3.0.0, eslint-plugin-html@3.1.0, gulp-eslint@4.0.0, koa-logger@3.0.1
|
||||
|
||||
*v0.1 2017年04月07日11:46:02*
|
||||
_v0.1 2017 年 04 月 07 日 11:46:02_
|
||||
|
||||
1. 升级koa为2.2.0版本。
|
||||
1. 升级 koa 为 2.2.0 版本。
|
||||
2. 升级了以下依赖版本到“建议版本”:
|
||||
|
||||
```
|
||||
@ -707,18 +704,18 @@ promise-mysql 3.0.0 3.0.1 3.0.1 koa2-API-scaffold
|
||||
sequelize 3.30.2 3.30.4 3.30.4 koa2-API-scaffold
|
||||
```
|
||||
|
||||
*v0.0.9_1 2017年03月30日15:51:03*
|
||||
_v0.0.9_1 2017 年 03 月 30 日 15:51:03_
|
||||
|
||||
1. 完善了gulpfile.js,不是重要的更新。
|
||||
1. 完善了 gulpfile.js,不是重要的更新。
|
||||
|
||||
*v0.0.9 2017年03月27日17:25:58*
|
||||
_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参数获取的示例。
|
||||
2. 修复了`src/lib/mysql.js`引用路径错误的 BUG。
|
||||
3. 修改了`src/controllers/api.js`GET 参数获取的示例。
|
||||
|
||||
*v0.0.8 2017年03月01日23:03:44*
|
||||
1、在src/app.js 18行 后添加了
|
||||
_v0.0.8 2017 年 03 月 01 日 23:03:44_
|
||||
1、在 src/app.js 18 行 后添加了
|
||||
|
||||
```
|
||||
jsonLimit: '20mb',
|
||||
@ -728,17 +725,17 @@ sequelize 3.30.2 3.30.4 3.30.4 koa2-API-
|
||||
|
||||
以免表单过长导致提交失败。
|
||||
|
||||
*v0.0.7 2017年02月18日19:01:48*
|
||||
1、修改了index.js、config.js(详情请看github记录),完善了对跨域的处理。 更新建议:对应github修改记录同步修改,方便将来部署调试。
|
||||
_v0.0.7 2017 年 02 月 18 日 19:01:48_
|
||||
1、修改了 index.js、config.js(详情请看 github 记录),完善了对跨域的处理。 更新建议:对应 github 修改记录同步修改,方便将来部署调试。
|
||||
|
||||
*v0.0.6 2017年02月17日21:17:23*
|
||||
1、修改了src/lib/sequelize.js文件,添加了对utf8mb4的支持(要求MySQL版本>5.5)。
|
||||
_v0.0.6 2017 年 02 月 17 日 21:17:23_
|
||||
1、修改了 src/lib/sequelize.js 文件,添加了对 utf8mb4 的支持(要求 MySQL 版本>5.5)。
|
||||
|
||||
*v0.0.5 2017年02月12日01:25:34*
|
||||
1、修改了gulpfile.js文件,在更改文件热重启的时候无需检查全部文件,仅检查改动文件,开发速度更快。
|
||||
2、修改了package.json中"start"项的值为"gulp nodemon"配合gulpfile.js文件的修改。
|
||||
_v0.0.5 2017 年 02 月 12 日 01:25:34_
|
||||
1、修改了 gulpfile.js 文件,在更改文件热重启的时候无需检查全部文件,仅检查改动文件,开发速度更快。
|
||||
2、修改了 package.json 中"start"项的值为"gulp nodemon"配合 gulpfile.js 文件的修改。
|
||||
|
||||
*v0.0.4 2017年02月07日15:57:17*
|
||||
_v0.0.4 2017 年 02 月 07 日 15:57:17_
|
||||
1、修改了部分配置文件的配置方法,使之更为规范(老版本用户无须理会,对程序没有影响)。
|
||||
2、修改了eslintrc.js文件中的JavaScript版本配置,改为ES8,兼容async、await。
|
||||
3、修改gulpfile.js文件第12行,检查`src/**/*.js`文件。
|
||||
2、修改了 eslintrc.js 文件中的 JavaScript 版本配置,改为 ES8,兼容 async、await。
|
||||
3、修改 gulpfile.js 文件第 12 行,检查`src/**/*.js`文件。
|
||||
|
9908
package-lock.json
generated
9908
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
27
package.json
27
package.json
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "koa2-API-scaffold",
|
||||
"name": "koa2-api-scaffold",
|
||||
"version": "1.0.1",
|
||||
"description": "Koa2 RESTful API 服务器的脚手架",
|
||||
"author": "yi-ge <a@wyr.me>",
|
||||
@ -19,32 +19,31 @@
|
||||
"koa-jwt": "^3.5.1",
|
||||
"koa-router": "^7.4.0",
|
||||
"koa-static2": "^0.1.8",
|
||||
"nodemailer": "^6.1.0",
|
||||
"promise-mysql": "^3.3.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"sequelize": "^5.2.12"
|
||||
"nodemailer": "^6.2.1",
|
||||
"promise-mysql": "^3.3.2",
|
||||
"sequelize": "^5.8.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.4.4",
|
||||
"@babel/core": "^7.4.5",
|
||||
"@babel/plugin-external-helpers": "^7.2.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.3",
|
||||
"@babel/preset-env": "^7.4.3",
|
||||
"@babel/register": "^7.4.0",
|
||||
"@babel/runtime": "^7.4.3",
|
||||
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||
"@babel/preset-env": "^7.4.5",
|
||||
"@babel/register": "^7.4.4",
|
||||
"@babel/runtime": "^7.4.5",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-jest": "^24.8.0",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-friendly-formatter": "^4.0.1",
|
||||
"eslint-plugin-html": "^5.0.3",
|
||||
"eslint-plugin-import": "^2.16.0",
|
||||
"eslint-plugin-jest": "^22.4.1",
|
||||
"eslint-plugin-node": "^8.0.1",
|
||||
"eslint-plugin-html": "^5.0.5",
|
||||
"eslint-plugin-import": "^2.17.3",
|
||||
"eslint-plugin-jest": "^22.6.4",
|
||||
"eslint-plugin-node": "^9.1.0",
|
||||
"eslint-plugin-promise": "^4.1.1",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-eslint": "^5.0.0",
|
||||
"gulp-nodemon": "^2.4.2",
|
||||
"jest": "^24.8.0",
|
||||
|
@ -1,31 +1,39 @@
|
||||
export let Get = (ctx) => {
|
||||
export const Get = (ctx, next) => {
|
||||
ctx.body = {
|
||||
result: 'get',
|
||||
name: ctx.params.name,
|
||||
para: ctx.query
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export let Post = async (ctx) => {
|
||||
export const Post = async (ctx, next) => {
|
||||
ctx.body = {
|
||||
result: 'post',
|
||||
name: ctx.params.name,
|
||||
para: ctx.request.body
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export let Put = (ctx) => {
|
||||
export const Put = (ctx, next) => {
|
||||
ctx.body = {
|
||||
result: 'put',
|
||||
name: ctx.params.name,
|
||||
para: ctx.request.body
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
export let Delete = (ctx) => {
|
||||
export const Delete = (ctx, next) => {
|
||||
ctx.body = {
|
||||
result: 'delete',
|
||||
name: ctx.params.name,
|
||||
para: ctx.request.body
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ const publicKey = fs.readFileSync(path.join(__dirname, '../../publicKey.pub'))
|
||||
/**
|
||||
* 检查授权是否合法
|
||||
*/
|
||||
export let CheckAuth = (ctx) => {
|
||||
const CheckAuth = (ctx, next) => {
|
||||
let token = ctx.request.header.authorization
|
||||
try {
|
||||
let decoded = jwt.verify(token.substr(7), publicKey)
|
||||
@ -39,11 +39,11 @@ export let CheckAuth = (ctx) => {
|
||||
}
|
||||
}
|
||||
|
||||
export let Post = (ctx) => {
|
||||
export const Post = (ctx, next) => {
|
||||
switch (ctx.params.action) {
|
||||
case 'check':
|
||||
return CheckAuth(ctx).then(result => { ctx.body = result })
|
||||
return CheckAuth(ctx).then(result => { ctx.body = result; next() })
|
||||
default:
|
||||
return CheckAuth(ctx).then(result => { ctx.body = result })
|
||||
return CheckAuth(ctx).then(result => { ctx.body = result; next() })
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,9 @@
|
||||
let requireDirectory = require('require-directory')
|
||||
module.exports = requireDirectory(module)
|
||||
import upload from './upload'
|
||||
import * as api from './api'
|
||||
import * as auth from './auth'
|
||||
|
||||
export default {
|
||||
upload,
|
||||
api,
|
||||
auth
|
||||
}
|
||||
|
@ -1,17 +1,15 @@
|
||||
import KoaRouter from 'koa-router'
|
||||
import controllers from '../controllers/index.js'
|
||||
import controllers from '../controllers'
|
||||
|
||||
const router = new KoaRouter()
|
||||
|
||||
router
|
||||
export default router
|
||||
.get('/public/get', function (ctx, next) {
|
||||
ctx.body = '禁止访问!'
|
||||
}) // 以/public开头则不用经过权限认证
|
||||
.all('/upload', controllers.upload.default)
|
||||
.get('/api/:name', controllers.api.Get)
|
||||
}) // 以/public开头则不经过权限认证
|
||||
.all('/upload', controllers.upload)
|
||||
.get('/public/api/:name', controllers.api.Get)
|
||||
.post('/api/:name', controllers.api.Post)
|
||||
.put('/api/:name', controllers.api.Put)
|
||||
.del('/api/:name', controllers.api.Delect)
|
||||
.del('/api/:name', controllers.api.Delete)
|
||||
.post('/auth/:action', controllers.auth.Post)
|
||||
|
||||
module.exports = router
|
||||
|
Loading…
Reference in New Issue
Block a user