diff --git a/README.md b/README.md index 73d94fd..e50863d 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/ ### Docker部署说明 ``` $ docker pull node -$ docker run -itd --name RESTfulAPI -v '$PWD':/usr/src/app -w /usr/src/app node node ./dist/app.js +$ docker run -itd --name RESTfulAPI -v `pwd`:/usr/src/app -w /usr/src/app node node ./dist/app.js ``` 通过'docker ps'查看是否运行成功及运行状态 @@ -146,17 +146,15 @@ $ docker run -itd -p 80:80 -p 443:443 -v `pwd`/nginx_config:/etc/nginx/conf.d ng > 引入插件的版本将会持续更新 引入的插件: -`` koa@2 koa-bodyparser@next 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 `` - -koa-multer': '^1.0.0', +`` koa@2 koa-body@2 koa-router@next koa-session2 koa-static2 koa-compose koa-multer 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框架  Synopsis: HTTP framework.  From: https://github.com/koajs/koa v2 -**koa-bodyparser**: body解析器 - Synopsis: A body parser for koa, base on co-body. support json, form and text type body. - From: https://github.com/koajs/logger +**koa-body**: body解析器 + Synopsis: A full-feature koa body parser middleware. + From: https://github.com/dlau/koa-body **koa-router**: Koa路由  Synopsis: Router middleware for koa. @@ -172,7 +170,11 @@ koa-multer': '^1.0.0', **koa-compose**: 多个中间件组合成一个  Synopsis: Compose several middleware into one. - From: https://github.com/koajs/compose + From: https://github.com/koajs/compose + +**koa-multer**: 处理数据中间件 + Synopsis: Multer is a node.js middleware for handling multipart/form-data for koa. + From: https://github.com/koa-modules/multer **require-directory**: 递归遍历指定目录  Synopsis: Recursively iterates over specified directory. @@ -232,7 +234,15 @@ koa-multer': '^1.0.0', **promise-mysql**: 操作MySQL数据库依赖  Synopsis: Promise Mysql. - From: https://github.com/lukeb-uk/node-promise-mysql + From: https://github.com/lukeb-uk/node-promise-mysql + +**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 支持Koa2的中间件列表:https://github.com/koajs/koa/wiki @@ -255,6 +265,9 @@ HTTP2推送中间件:https://github.com/silenceisgolden/koa-server-push  Synopsis: Development style logger middleware for Koa.  From: https://github.com/koajs/logger +**koa-onerror**: +Koa的错误拦截中间件,需要配合上面的插件使用:https://github.com/koajs/onerror + ## 目录结构说明 ```bash diff --git a/assets/update/.gitkeep b/assets/uploads/.gitkeep similarity index 100% rename from assets/update/.gitkeep rename to assets/uploads/.gitkeep diff --git a/config/main.js b/config/main.js index 403e748..bfcbf38 100644 --- a/config/main.js +++ b/config/main.js @@ -2,10 +2,11 @@ import path from 'path' export let SystemConfig = { HTTP_server_type: 'http://', // HTTP服务器地址,包含"http://"或"https://" - HTTP_server_host: 'localhost',// HTTP服务器地址,请勿添加"http://" - HTTP_server_port: '3000',// HTTP服务器端口号 + HTTP_server_host: 'localhost', // HTTP服务器地址,请勿添加"http://" + HTTP_server_port: '3000', // HTTP服务器端口号 System_country: 'zh-cn', // 所在国家的国家代码 - System_plugin_path: path.join(__dirname, "plugins/"), // 插件路径 + System_plugin_path: path.join(__dirname, "../src/plugins"), // 插件路径 + Session_Key: 'RESTfulAPI', // 生产环境务必随机设置一个值 mysql_host: 'localhost', // MySQL服务器地址 mysql_user: 'root', // 数据库用户名 mysql_password: 'root', // 数据库密码 @@ -13,3 +14,10 @@ export let SystemConfig = { mysql_port: 3306, // 数据库端口号 mysql_prefix: 'api_' // 默认"api_" } + +export let SendEmail = { + service: 'smtp.abcd.com', // SMTP服务提供商域名 + username: 'postmaster%40abcd.com', // 用户名/用户邮箱 + password: 'password', // 邮箱密码 + sender_address: '"XX平台 👥" ' +} diff --git a/package.json b/package.json index 52e3008..834b77b 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,16 @@ }, "dependencies": { "koa": "^2.0.0", - "koa-bodyparser": "^3.2.0", + "koa-body": "^2.0.0", "koa-compose": "^2.5.1", + "koa-multer": "^1.0.1", "koa-router": "^7.0.1", "koa-session2": "^1.0.8", + "mysql": "^2.12.0", "nodemailer": "^2.7.2", "promise-mysql": "^3.0.0", - "require-directory": "^2.1.1" + "require-directory": "^2.1.1", + "sequelize": "^3.29.0" }, "devDependencies": { "babel-cli": "^6.22.2", diff --git a/src/app.js b/src/app.js index 4767ff4..e7fb9da 100644 --- a/src/app.js +++ b/src/app.js @@ -1,32 +1,23 @@ import Koa2 from 'koa' -import KoaBodyParser from 'koa-bodyparser' +import KoaBody from 'koa-body' import KoaSession from 'koa-session2' import KoaStatic from 'koa-static2' import { SystemConfig } from '../config/main.js' import path from 'path' - import MainRoutes from './routes/main-routes' import ErrorRoutes from './routes/error-routes' -import PluginLoader from './tool/PluginLoader' +// import PluginLoader from './tool/PluginLoader' const app = new Koa2() -const BodyParser = new KoaBodyParser() const env = process.env.NODE_ENV || 'development' // Current mode -app.use(BodyParser({ - detectJSON: function (ctx) { - return /\.json$/i.test(ctx.path) - }, - extendTypes: { - json: ['application/x-javascript'] // will parse application/x-javascript type body as a JSON string - }, - onerror: function (err, ctx) { - ctx.throw('body parse error:' + err, 422) - } +app.use(KoaBody({ + multipart: true + // formidable: {uploadDir: path.join(__dirname, '../../../assets/uploads/')} })) // Processing request .use(KoaStatic('assets', path.resolve(__dirname, '../assets'))) // Static resource -.use(KoaSession({key: 'RESTfulAPI'})) // Set Session 生产环境务必随机设置一个值 -.use(PluginLoader(SystemConfig.System_plugin_path)) +.use(KoaSession({key: SystemConfig.Session_Key})) // Set Session +// .use(PluginLoader(SystemConfig.System_plugin_path)) .use((ctx, next) => { if (ctx.request.header.host.split(':')[0] === 'api.XXX.com' || ctx.request.header.host.split(':')[0] === '127.0.0.1') { ctx.set('Access-Control-Allow-Origin', '*') diff --git a/src/controllers/api.js b/src/controllers/api.js index e69de29..37465ab 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -0,0 +1,30 @@ +export let Get = (ctx) => { + ctx.body = { + result: 'get', + name: ctx.params.name + } +} + +export let Post = (ctx) => { + ctx.body = { + result: 'post', + name: ctx.params.name, + para: ctx.request.body.para + } +} + +export let Put = (ctx) => { + ctx.body = { + result: 'put', + name: ctx.params.name, + para: ctx.request.body.para + } +} + +export let Delect = (ctx) => { + ctx.body = { + result: 'delect', + name: ctx.params.name, + para: ctx.request.body.para + } +} diff --git a/src/controllers/upload.js b/src/controllers/upload.js new file mode 100644 index 0000000..068c270 --- /dev/null +++ b/src/controllers/upload.js @@ -0,0 +1,35 @@ +import multer from 'koa-multer' +import path from 'path' + +/*** + * 说明:该方法只支持:`multipart/form-data`方式的上传。postman可以调试。 + */ + +let storage = multer.diskStorage({ + // 设置上传后文件路径 + destination: function (req, file, cb) { + cb(null, path.join(__dirname, '../../../assets/uploads/')) + }, + // 给上传文件重命名,获取添加后缀名 + filename: function (req, file, cb) { + let fileFormat = (file.originalname).split('.') + cb(null, Date.now() + '.' + fileFormat[fileFormat.length - 1]) + } +}) + +export let upload = multer({ + storage: storage, + // dest: 'uploads/', //上传文件保存的路径,如果你想在上传时进行更多的控制, 你可以使用storage选项替代dest. Multer 具有 DiskStorage 和 MemoryStorage 两个存储引擎; 另外还可以从第三方获得更多可用的引擎. + // fileFilter: function (req, file, cb) { + // let mimetypes = (['text/*', 'image/*', 'video/*', 'audio/*', 'application/zip']).join(','); + // let testItems = file.mimetype.split('/'); + // if ((new RegExp('\b' + testItems[0] + '/\*', 'i')).test(mimetypes) || (new RegExp('\*/' + testItems[1] + '\b', 'i')).test(mimetypes) || (new RegExp('\b' + testItems[0] + '/' + testItems[1] + '\b', 'i')).test(mimetypes)) { + // cb(null, true); + // } else { + // return cb(new Error('Only image, plain text, audio, video and zip format files are allowed!'), false); + // } + // }, // fileFilter要在这里声明才行,用instance.fileFilter = funciton(){};是不管用的, + limits: { + fileSize: 200 * 1024 * 1024 // Max file size in bytes (20 MB) 限制上传的文件大小,不设置则是无限 + } +}) diff --git a/src/lib/sequelize.js b/src/lib/sequelize.js new file mode 100644 index 0000000..a48c867 --- /dev/null +++ b/src/lib/sequelize.js @@ -0,0 +1,12 @@ +import Sequelize from 'sequelize' +import { SystemConfig } from '../config/main' + +export default new Sequelize(SystemConfig.mysql_database, SystemConfig.mysql_user, SystemConfig.mysql_password, { + host: SystemConfig.mysql_host, + dialect: 'mysql', + pool: { + max: 50, + min: 0, + idle: 10000 + } +}) diff --git a/src/plugin/smtp_sendemail/index.js b/src/plugins/smtp_sendemail/index.js similarity index 81% rename from src/plugin/smtp_sendemail/index.js rename to src/plugins/smtp_sendemail/index.js index 65b6026..4cb0957 100644 --- a/src/plugin/smtp_sendemail/index.js +++ b/src/plugins/smtp_sendemail/index.js @@ -1,4 +1,5 @@ import nodemailer from 'nodemailer' +import { SendEmail } from '../../../config/main' // 发送Email(目前使用的是阿里云SMTP发送邮件) // receivers 目标邮箱,可以用英文逗号分隔多个。(我没试过) @@ -10,11 +11,11 @@ import nodemailer from 'nodemailer' // info 是返回的消息,可能是结果的文本,也可能是对象。(这个错误不要暴露给用户) export let sendemail = (receivers, subject, text, html) => { return new Promise(function (resolve) { - let transporter = nodemailer.createTransport('smtp://postmaster%40abcd.com:password@smtp.abcd.com') + let transporter = nodemailer.createTransport('smtp://' + SendEmail.username + ':' + SendEmail.password + '@' + SendEmail.service) // setup e-mail data with unicode symbols let mailOptions = { - from: '"XX平台 👥" ', // sender address + from: SendEmail.sender_address, // sender address to: receivers, subject: subject, text: text || 'Hello world 🐴', // plaintext body diff --git a/src/routes/main-routes.js b/src/routes/main-routes.js index f69ce0d..f446134 100644 --- a/src/routes/main-routes.js +++ b/src/routes/main-routes.js @@ -1,5 +1,5 @@ import KoaRouter from 'koa-router' -// import controllers from '../controllers/index.js' +import controllers from '../controllers/index.js' const router = new KoaRouter() @@ -7,9 +7,17 @@ router .get('/', function (ctx, next) { ctx.body = '禁止访问!' }) // HOME 路由 - // .get('/api/:api_type/:name', controllers.api.api_get) - // .put('/api/:api_type/:name', controllers.api_put.api_put - // .post('/api/:api_type/:name', controllers.api.default) - // .delect('/api/:api_type/:name', controllers.api.default) + .all('/upload', controllers.upload.upload.array('file'), function (ctx, next) { // 上传到本地示例 + return new Promise(function (resolve, reject) { + // 允许跨域,正式环境要改为对应域名 + ctx.set('Access-Control-Allow-Origin', '*') + // ctx.req.files.filename = ctx.req.files.path + resolve(ctx.body = ctx.req.files) + }) + }) + .get('/api/:name', controllers.api.Get) + .post('/api/:name', controllers.api.Post) + .put('/api/:name', controllers.api.Put) + .del('/api/:name', controllers.api.Delect) module.exports = router diff --git a/src/tool/Common.js b/src/tool/Common.js index be9b000..3b0b345 100644 --- a/src/tool/Common.js +++ b/src/tool/Common.js @@ -34,8 +34,8 @@ export let OptionFormat = (GetOptions) => { // 替换SQL字符串中的前缀 export let SqlFormat = (str) => { - if (SystemConfig.mysql_prefix !== 'bm_') { - str = str.replace(/bm_/g, SystemConfig.mysql_prefix) + if (SystemConfig.mysql_prefix !== 'api_') { + str = str.replace(/api_/g, SystemConfig.mysql_prefix) } return str }