From 750ec4e31d27f1f2572580a59e6a8fe7a261c871 Mon Sep 17 00:00:00 2001 From: Jack Hu Date: Wed, 30 Mar 2016 13:04:02 +0800 Subject: [PATCH] update to v1.1.0 --- .travis.yml | 1 + History.md | 8 +++++++ README.md | 28 +++++++++++------------- gulp/server.js | 3 +++ logs/development-error.log.0 | 6 ----- package.json | 7 +++--- server/api/article/article.controller.js | 16 ++++++++------ server/api/mobile/index.js | 10 ++++----- server/api/mobile/mobile.controller.js | 13 ++++++----- server/config/env/development.js | 3 +++ server/config/env/index.js | 6 ++++- server/config/env/production.js | 3 +++ server/config/env/test.js | 3 +++ server/config/koa.js | 4 ++-- server/util/qiniu/index.js | 10 ++++----- server/util/redis/index.js | 14 ++++++++++++ server/util/tools/index.js | 3 ++- test/api/article.test.js | 25 +++++++++++++-------- 18 files changed, 103 insertions(+), 60 deletions(-) delete mode 100644 logs/development-error.log.0 create mode 100644 server/util/redis/index.js diff --git a/.travis.yml b/.travis.yml index 29d4eb5..f852181 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ addons: services: - mongodb + - redis-server before_install: - $CXX --version diff --git a/History.md b/History.md index 1202e85..39bf34a 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,11 @@ +1.1.0 / 2016-03-30 +================== + +* 增加redis支持 +* 使用koa-redis 替换 koa-generic-session-mongo +* 使用redis 缓存首页图片. + + 1.0.1 / 2016-02-29 ================== diff --git a/README.md b/README.md index a10de59..b99a634 100644 --- a/README.md +++ b/README.md @@ -10,21 +10,17 @@ [coveralls-url]: https://coveralls.io/github/jackhutu/jackblog-api-koa?branch=master ## 简介 -Jackblog 是使用 Node.js + MongoDB + 其它客户端框架, 开发的个人博客系统,前后端分离,仿简书模板.此为服务端koa版. -服务端有: -[express版](https://github.com/jackhutu/jackblog-api-express) -[koa版](https://github.com/jackhutu/jackblog-api-koa) -客户端有: -[angular1.x版](https://github.com/jackhutu/jackblog-angular1) -[react redux 版](https://github.com/jackhutu/jackblog-react-redux) -[vue 版](https://github.com/jackhutu/jackblog-vue) -移动端有: -[react native 版](https://github.com/jackhutu/jackblog-react-native-redux) +Jackblog 是使用 Node.js + MongoDB + 其它客户端框架开发的个人博客系统,前后端分离,仿简书模板. +服务端有: [express 版](https://github.com/jackhutu/jackblog-api-express) , [koa 版](https://github.com/jackhutu/jackblog-api-koa) +客户端有: [angular1.x 版](https://github.com/jackhutu/jackblog-angular1) , [angular2.x 版](https://github.com/jackhutu/jackblog-angular2) , [react redux 版](https://github.com/jackhutu/jackblog-react-redux) , [vue 版](https://github.com/jackhutu/jackblog-vue) +移动端有: [react native 版](https://github.com/jackhutu/jackblog-react-native-redux) +##### 此为服务端koa版, 为客户端提供api. ## 环境准备 ``` node.js 4.0+ mognodb 3.0+ +redis 2.8+ ``` ## 配置 @@ -42,14 +38,11 @@ mognodb 3.0+ ## 开发 ``` +$ git clone git@github.com:jackhutu/jackblog-api-koa.git +$ cd jackblog-api-koa $ npm install $ gulp serve ``` -配合客户端测试的测试模式 - -``` -$ gulp serve:test -``` ## 线上布署 ``` @@ -61,6 +54,11 @@ $ pm2 start process.json ``` $ gulp test ``` +配合客户端测试的测试模式 + +``` +$ gulp serve:test +``` ## License MIT \ No newline at end of file diff --git a/gulp/server.js b/gulp/server.js index 79c909d..25dc7aa 100644 --- a/gulp/server.js +++ b/gulp/server.js @@ -14,6 +14,9 @@ gulp.task('nodemon',function () { watch: [ path.join(config.paths.server,'/') ], + "execMap": { + "js": "node --harmony" + }, env: { 'NODE_ENV': 'development','DEBUG': pkg.name +':*' } }) }); diff --git a/logs/development-error.log.0 b/logs/development-error.log.0 deleted file mode 100644 index bfa3849..0000000 --- a/logs/development-error.log.0 +++ /dev/null @@ -1,6 +0,0 @@ -{"name":"jackblog","hostname":"hugongzideMacBook-Air.local","pid":49622,"level":50,"msg":"hello","time":"2016-01-27T04:48:19.454Z","v":0} -{"name":"jackblog","hostname":"hugongzideMacBook-Air.local","pid":49795,"level":50,"msg":"hello","time":"2016-01-27T04:51:58.809Z","v":0} -{"name":"jackblog","hostname":"hugongzideMacBook-Air.local","pid":49881,"level":50,"msg":"hello","time":"2016-01-27T04:53:22.933Z","v":0} -{"name":"jackblog","hostname":"hugongzideMacBook-Air.local","pid":50542,"level":50,"登录用户名错误!":{"username":"hutufeia2009@sina.comfff"},"msg":"","time":"2016-01-27T05:06:59.382Z","v":0} -{"name":"jackblog","hostname":"hugongzideMacBook-Air.local","pid":50630,"level":50,"msg":"","username":"hutufeia2009@sina.comfff","time":"2016-01-27T05:08:53.900Z","v":0} -{"name":"jackblog","hostname":"hugongzideMacBook-Air.local","pid":50722,"level":50,"msg":"登录用户名错误 { username: 'hutufeia2009@sina.comfff' }","time":"2016-01-27T05:10:39.517Z","v":0} diff --git a/package.json b/package.json index 4bdcdad..25574f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jackblog-api-koa", - "version": "1.0.1", + "version": "1.1.0", "description": "jackblog API koa版", "main": "server/app.js", "scripts": { @@ -28,19 +28,20 @@ "ccap": "^0.6.4", "co": "^4.6.0", "debug": "^2.2.0", + "ioredis": "^1.15.1", "koa": "^1.1.2", "koa-bodyparser": "^2.0.1", "koa-compose": "^2.3.0", "koa-compress": "^1.0.8", "koa-cors": "0.0.16", "koa-generic-session": "^1.10.1", - "koa-generic-session-mongo": "^0.2.4", "koa-json": "^1.1.1", "koa-jwt": "^1.1.2", "koa-logger": "^1.3.0", "koa-multer": "0.0.2", "koa-onerror": "^1.2.1", "koa-passport": "^1.2.0", + "koa-redis": "^2.0.1", "koa-response-time": "^1.0.2", "koa-router": "^5.3.0", "lodash": "^4.0.0", @@ -55,7 +56,7 @@ }, "devDependencies": { "del": "^2.2.0", - "gulp": "^3.9.0", + "gulp": "^3.9.1", "gulp-coveralls": "^0.1.4", "gulp-env": "^0.4.0", "gulp-istanbul": "^0.10.3", diff --git a/server/api/article/article.controller.js b/server/api/article/article.controller.js index 0c03b66..44418c7 100644 --- a/server/api/article/article.controller.js +++ b/server/api/article/article.controller.js @@ -11,6 +11,7 @@ const URL = require('url'); const MarkdownIt = require('markdown-it'); const config = require('../../config/env'); const tools = require('../../util/tools'); +const redis = require('../../util/redis'); //添加博客 exports.addArticle = function *() { @@ -265,21 +266,22 @@ exports.getPrenext = function *(next) { } //获取首页图片 exports.getIndexImage = function *() { - //直接从七牛获取会很慢,改为从配置数组中获取. - if(!config.indexImages || config.indexImages.length < 1){ + //从redis中获取 + const imagesCount = yield redis.llen('indexImages') + if(!imagesCount || imagesCount < 1){ this.status = 200; this.body = {success:true,img:config.defaultIndexImage}; try{ - const result = yield qiniuHelper.list('blog/index','',10) - config.indexImages = result.items.map(function (item) { - return config.qiniu.domain + item.key + '-600x1500q80'; + const result = yield qiniuHelper.list('blog/index','',30) + result.items.map(function (item) { + redis.lpush('indexImages',config.qiniu.domain + item.key + '-600x1500q80'); }) }catch(err){ - config.indexImages = [] + redis.del('indexImages') } return; }else{ - const images = config.indexImages; + const images = yield redis.lrange('indexImages', 0, 30) const index = _.random(images.length - 1); this.status = 200; return this.body = {success:true,img:images[index]}; diff --git a/server/api/mobile/index.js b/server/api/mobile/index.js index eb880a9..89b9e44 100644 --- a/server/api/mobile/index.js +++ b/server/api/mobile/index.js @@ -1,8 +1,8 @@ -'use strict'; +'use strict' -const router = require("koa-router")(); -const controller = require('./mobile.controller'); +const router = require("koa-router")() +const controller = require('./mobile.controller') -router.get('/getApps',controller.getApps); +router.get('/getApps',controller.getApps) -module.exports = router; \ No newline at end of file +module.exports = router \ No newline at end of file diff --git a/server/api/mobile/mobile.controller.js b/server/api/mobile/mobile.controller.js index 8661ba1..b65d521 100644 --- a/server/api/mobile/mobile.controller.js +++ b/server/api/mobile/mobile.controller.js @@ -1,11 +1,12 @@ -'use strict'; -const config = require('../../config/env'); +'use strict' + +const config = require('../../config/env') exports.getApps = function *(next){ if(config.apps){ - this.status = 200; - this.body = {success:true,data:config.apps}; + this.status = 200 + this.body = {success:true,data:config.apps} }else{ - this.throw(404); + this.throw(404) } -}; +} diff --git a/server/config/env/development.js b/server/config/env/development.js index 10a8a35..0f214eb 100644 --- a/server/config/env/development.js +++ b/server/config/env/development.js @@ -6,6 +6,9 @@ module.exports = { mongo: { uri: 'mongodb://localhost/jackblog-dev' }, + redis: { + db: 0 + }, seedDB: true, session:{ cookie: {maxAge: 60000*5} diff --git a/server/config/env/index.js b/server/config/env/index.js index 7e9f834..4f4dcb8 100644 --- a/server/config/env/index.js +++ b/server/config/env/index.js @@ -15,6 +15,10 @@ var all = { } } }, + redis: { + host: '127.0.0.1', + port: 6379 + }, seedDB: false, session:{ secrets: 'jackblog-secret', @@ -27,7 +31,7 @@ var all = { bucket:"bucket" //七牛空间名称 }, //默认首页图片. - defaultIndexImage:"http://upload.jackhu.top/blog/index/8x7hVJvpE3Z6ruwgtd2G.jpg", + defaultIndexImage:"http://upload.jackhu.top/blog/index/default.jpg-600x1500q80", github:{ clientID:"github", clientSecret:"clientSecret", diff --git a/server/config/env/production.js b/server/config/env/production.js index da1ad28..279828c 100644 --- a/server/config/env/production.js +++ b/server/config/env/production.js @@ -11,6 +11,9 @@ module.exports = { pass:'pass' //生产环境密码 } }, + redis: { + db: 1 + }, session:{ cookie: {domain:'.jackhu.top',maxAge: 60000*5} } diff --git a/server/config/env/test.js b/server/config/env/test.js index 4cf4878..f05b2be 100644 --- a/server/config/env/test.js +++ b/server/config/env/test.js @@ -6,6 +6,9 @@ module.exports = { mongo: { uri: 'mongodb://localhost/jackblog-test' }, + redis: { + db: 2 + }, port: process.env.PORT || 8080, seedDB: true }; \ No newline at end of file diff --git a/server/config/koa.js b/server/config/koa.js index a5e0510..fd43145 100644 --- a/server/config/koa.js +++ b/server/config/koa.js @@ -2,7 +2,7 @@ const path = require("path"); const session = require("koa-generic-session"); -const MongoStore = require("koa-generic-session-mongo"); +const RedisStore = require('koa-redis'); const responseTime = require("koa-response-time"); const logger = require("koa-logger"); const json = require('koa-json') @@ -25,7 +25,7 @@ module.exports = function(app) { app.keys = [config.session.secrets]; app.use(session({ key: "jackblog.sid", - store: new MongoStore(config.mongo), + store: new RedisStore(config.redis), cookie: config.session.cookie })); app.use(passport.initialize()); diff --git a/server/util/qiniu/index.js b/server/util/qiniu/index.js index 3c3d501..7c33573 100644 --- a/server/util/qiniu/index.js +++ b/server/util/qiniu/index.js @@ -1,10 +1,10 @@ 'use strict'; -var _ = require('lodash'); -var config = require('../../config/env'); -var mongoose = require('mongoose'); -var Promise = require("bluebird"); -var qiniu = require('qiniu'); +const _ = require('lodash'); +const config = require('../../config/env'); +const mongoose = require('mongoose'); +const Promise = require("bluebird"); +const qiniu = require('qiniu'); qiniu.conf.ACCESS_KEY = config.qiniu.app_key; qiniu.conf.SECRET_KEY = config.qiniu.app_secret; diff --git a/server/util/redis/index.js b/server/util/redis/index.js new file mode 100644 index 0000000..df29dfe --- /dev/null +++ b/server/util/redis/index.js @@ -0,0 +1,14 @@ +'use strict' + +const _ = require('lodash') +const Redis = require("ioredis") +const config = require('../../config/env') +const logger = require('../logs').logger + +const client = new Redis(config.redis) + +client.on("error", function (err) { + logger.error('redis error', err) +}) + +exports = module.exports = client \ No newline at end of file diff --git a/server/util/tools/index.js b/server/util/tools/index.js index de4450c..35c865e 100644 --- a/server/util/tools/index.js +++ b/server/util/tools/index.js @@ -1,5 +1,6 @@ "use strict"; -var _ = require('lodash'); + +const _ = require('lodash'); //生成随机字符串 exports.randomString = function (len) {   len = len || 12; diff --git a/test/api/article.test.js b/test/api/article.test.js index e323ea4..8f805d9 100644 --- a/test/api/article.test.js +++ b/test/api/article.test.js @@ -7,9 +7,10 @@ const mongoose = require('mongoose'); const User = mongoose.model('User'); const Article = mongoose.model('Article'); const Logs = mongoose.model('Logs'); -const qiniuHelper = require('../../server/util/qiniu'); const sinon = require('sinon'); const co = require("co"); +const qiniuHelper = require('../../server/util/qiniu'); +const redis = require('../../server/util/redis'); const authHelper = require('../middlewares/authHelper'); describe('test/api/article.test.js',function () { @@ -27,6 +28,7 @@ describe('test/api/article.test.js',function () { yield User.findByIdAndRemove(mockAdminId); yield Article.remove(); yield Logs.remove(); + yield redis.del('indexImages') })); describe('post /article/addArticle',function () { @@ -332,8 +334,6 @@ describe('test/api/article.test.js',function () { }); }); - - describe('get /article/getIndexImage',function () { var stubQiniu; beforeEach(function () { @@ -343,21 +343,28 @@ describe('test/api/article.test.js',function () { qiniuHelper.list.restore(); }); - it('should return index image',function (done) { - stubQiniu.returns(Promise.resolve({items:[{ - key:'aaaabbbbdddddcccc' - }]})); + it('should return default index image',function (done) { + stubQiniu.returns(Promise.resolve({items:[1, 2, 3, 4, 5].map(i=>({key:i}))})); request.get('/article/getIndexImage') .expect(200) .end(function (err,res) { if (err) return done(err); res.body.success.should.be.true(); - res.body.img.should.startWith('http://upload.jackhu.top'); + res.body.img.should.startWith('http://upload.jackhu.top/blog/index/default.jpg'); stubQiniu.calledOnce.should.be.true(); done(); }); }); - + it('should return redis image',function (done) { + request.get('/article/getIndexImage') + .expect(200) + .end(function (err,res) { + if (err) return done(err); + res.body.success.should.be.true(); + res.body.img.should.be.String; + done(); + }); + }); }); describe('get /article/:id/getPrenext', function() {