From 599d208687d3c96f85237e27dbcef8c8a4839fd0 Mon Sep 17 00:00:00 2001 From: Martin Iwanowski Date: Mon, 25 Apr 2016 15:14:52 +0200 Subject: [PATCH 1/6] reference app.wrappers[] for each mw --- lib/application.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/application.js b/lib/application.js index 551bfab9c..4f54e2b24 100644 --- a/lib/application.js +++ b/lib/application.js @@ -42,6 +42,7 @@ module.exports = class Application extends Emitter { this.proxy = false; this.middleware = []; + this.wrappers = [] this.subdomainOffset = 2; this.env = process.env.NODE_ENV || 'development'; this.context = Object.create(context); @@ -110,6 +111,9 @@ module.exports = class Application extends Emitter { 'https://github.com/koajs/koa/tree/v2.x#old-signature-middleware-v1x'); fn = convert(fn); } + + if (this.wrappers.length) fn._wrappers = this.wrappers + debug('use %s', fn._name || fn.name || '-'); this.middleware.push(fn); return this; From b618128af1593123f66ea1c7aa302f2025ff742e Mon Sep 17 00:00:00 2001 From: Martin Iwanowski Date: Mon, 25 Apr 2016 15:38:50 +0200 Subject: [PATCH 2/6] linting errors, my bad --- lib/application.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/application.js b/lib/application.js index 4f54e2b24..09fa2a750 100644 --- a/lib/application.js +++ b/lib/application.js @@ -42,7 +42,7 @@ module.exports = class Application extends Emitter { this.proxy = false; this.middleware = []; - this.wrappers = [] + this.wrappers = []; this.subdomainOffset = 2; this.env = process.env.NODE_ENV || 'development'; this.context = Object.create(context); @@ -112,7 +112,7 @@ module.exports = class Application extends Emitter { fn = convert(fn); } - if (this.wrappers.length) fn._wrappers = this.wrappers + if (this.wrappers.length) fn._wrappers = this.wrappers; debug('use %s', fn._name || fn.name || '-'); this.middleware.push(fn); From cae68cbaafce6c3902b46f306a0e4d14a25a1055 Mon Sep 17 00:00:00 2001 From: Martin Iwanowski Date: Mon, 2 May 2016 09:25:32 +0200 Subject: [PATCH 3/6] a more solidified implementation example --- lib/application.js | 8 ++- test/application/index.js | 126 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/lib/application.js b/lib/application.js index 09fa2a750..815848147 100644 --- a/lib/application.js +++ b/lib/application.js @@ -99,11 +99,14 @@ module.exports = class Application extends Emitter { * Old-style middleware will be converted. * * @param {Function} fn + * @param {Object} opts * @return {Application} self * @api public */ - use(fn) { + use(fn, opts) { + opts = opts || { wrappers: this.wrappers }; + if (typeof fn !== 'function') throw new TypeError('middleware must be a function!'); if (isGeneratorFunction(fn)) { deprecate('Support for generators will been removed in v3. ' + @@ -112,7 +115,8 @@ module.exports = class Application extends Emitter { fn = convert(fn); } - if (this.wrappers.length) fn._wrappers = this.wrappers; + if (opts.wrappers && Array.isArray(opts.wrappers)) + fn._wrappers = opts.wrappers; debug('use %s', fn._name || fn.name || '-'); this.middleware.push(fn); diff --git a/test/application/index.js b/test/application/index.js index 96710ec28..6bdc2a498 100644 --- a/test/application/index.js +++ b/test/application/index.js @@ -6,6 +6,132 @@ const assert = require('assert'); const Koa = require('../..'); describe('app', () => { + it('should wrap mw correctly', done => { + const app = new Koa(); + const composed = [] + + app.wrappers = [(ctx, next) => { + composed.push('pre'); + return next().then(() => { + composed.push('post') + }) + }] + + app.use((ctx, next) => { + composed.push('middleware 1') + return next() + }) + + app.use((ctx, next) => { + composed.push('middleware 2') + return next() + }) + + request(app.listen()) + .get('/') + .end(() => { + composed.should.eql([ + 'pre', + 'middleware 1', + 'pre', + 'middleware 2', + 'post', + 'post' + ]) + done(); + }); + }) + + it ('should not wrap when opts.wrappers = false', done => { + const app = new Koa(); + const wrapped = [] + + app.wrappers = [(ctx, next) => { + wrapped.push('pre'); + return next().then(() => { + wrapped.push('post') + }) + }] + + app.use((ctx, next) => { + wrapped.push('middleware 1') + return next() + }, { wrappers: false }) + + app.use((ctx, next) => { + wrapped.push('middleware 2') + return next() + }, { wrappers: false }) + + request(app.listen()) + .get('/') + .end(() => { + wrapped.should.eql(['middleware 1', 'middleware 2']) + done(); + }); + }) + + it ('should not wrap when app.wrappers is false', done => { + const app = new Koa(); + const wrapped = []; + app.wrappers = false; + + app.use((ctx, next) => { + wrapped.push('middleware 1') + return next() + }) + + request(app.listen()) + .get('/') + .end(() => { + wrapped.should.eql(['middleware 1']) + done(); + }); + }) + + it ('should wrap with provided opts.wrappers', done => { + const app = new Koa(); + const wrapped = [] + + const profiler = (ctx, next) => { + wrapped.push('profiler pre'); + return next().then(() => { + wrapped.push('profiler post') + }) + } + + app.wrappers = [(ctx, next) => { + wrapped.push('should not wrap pre'); + return next().then(() => { + wrapped.push('should not wrap post') + }) + }] + + app.use((ctx, next) => { + wrapped.push('middleware 1') + return next() + }, { + wrappers: [profiler] + }) + + app.use((ctx, next) => { + wrapped.push('middleware 2') + return next() + }, { wrappers: false }) + + request(app.listen()) + .get('/') + .end(() => { + wrapped.should.eql([ + 'profiler pre', + 'middleware 1', + 'middleware 2', + 'profiler post' + ]) + done(); + }); + }) + it('should handle socket errors', done => { const app = new Koa(); From 8025657e42653399cd4d0ca2626c600d56073ac1 Mon Sep 17 00:00:00 2001 From: Martin Iwanowski Date: Mon, 2 May 2016 10:57:52 +0200 Subject: [PATCH 4/6] wrap implementation --- lib/application.js | 23 ++++--- test/application/index.js | 126 ------------------------------------ test/application/wrap.js | 133 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 134 deletions(-) create mode 100644 test/application/wrap.js diff --git a/lib/application.js b/lib/application.js index 815848147..98aeb5f29 100644 --- a/lib/application.js +++ b/lib/application.js @@ -9,7 +9,7 @@ const isGeneratorFunction = require('is-generator-function'); const debug = require('debug')('koa:application'); const onFinished = require('on-finished'); const response = require('./response'); -const compose = require('koa-compose'); +const compose = require('../../compose'); const isJSON = require('koa-is-json'); const context = require('./context'); const request = require('./request'); @@ -99,14 +99,11 @@ module.exports = class Application extends Emitter { * Old-style middleware will be converted. * * @param {Function} fn - * @param {Object} opts * @return {Application} self * @api public */ - use(fn, opts) { - opts = opts || { wrappers: this.wrappers }; - + use(fn) { if (typeof fn !== 'function') throw new TypeError('middleware must be a function!'); if (isGeneratorFunction(fn)) { deprecate('Support for generators will been removed in v3. ' + @@ -115,11 +112,21 @@ module.exports = class Application extends Emitter { fn = convert(fn); } - if (opts.wrappers && Array.isArray(opts.wrappers)) - fn._wrappers = opts.wrappers; - debug('use %s', fn._name || fn.name || '-'); this.middleware.push(fn); + if (this.wrappers && this.wrappers.length) this.wrap(); + return this; + } + + wrap(wrappers) { + wrappers = wrappers || this.wrappers; + if (!wrappers || !this.wrappers.length) return this; + this.middleware[this.middleware.length - 1]._wrappers = wrappers; + return this; + } + + dewrap() { + delete this.middleware[this.middleware.length - 1]._wrappers; return this; } diff --git a/test/application/index.js b/test/application/index.js index 6bdc2a498..96710ec28 100644 --- a/test/application/index.js +++ b/test/application/index.js @@ -6,132 +6,6 @@ const assert = require('assert'); const Koa = require('../..'); describe('app', () => { - it('should wrap mw correctly', done => { - const app = new Koa(); - const composed = [] - - app.wrappers = [(ctx, next) => { - composed.push('pre'); - return next().then(() => { - composed.push('post') - }) - }] - - app.use((ctx, next) => { - composed.push('middleware 1') - return next() - }) - - app.use((ctx, next) => { - composed.push('middleware 2') - return next() - }) - - request(app.listen()) - .get('/') - .end(() => { - composed.should.eql([ - 'pre', - 'middleware 1', - 'pre', - 'middleware 2', - 'post', - 'post' - ]) - done(); - }); - }) - - it ('should not wrap when opts.wrappers = false', done => { - const app = new Koa(); - const wrapped = [] - - app.wrappers = [(ctx, next) => { - wrapped.push('pre'); - return next().then(() => { - wrapped.push('post') - }) - }] - - app.use((ctx, next) => { - wrapped.push('middleware 1') - return next() - }, { wrappers: false }) - - app.use((ctx, next) => { - wrapped.push('middleware 2') - return next() - }, { wrappers: false }) - - request(app.listen()) - .get('/') - .end(() => { - wrapped.should.eql(['middleware 1', 'middleware 2']) - done(); - }); - }) - - it ('should not wrap when app.wrappers is false', done => { - const app = new Koa(); - const wrapped = []; - app.wrappers = false; - - app.use((ctx, next) => { - wrapped.push('middleware 1') - return next() - }) - - request(app.listen()) - .get('/') - .end(() => { - wrapped.should.eql(['middleware 1']) - done(); - }); - }) - - it ('should wrap with provided opts.wrappers', done => { - const app = new Koa(); - const wrapped = [] - - const profiler = (ctx, next) => { - wrapped.push('profiler pre'); - return next().then(() => { - wrapped.push('profiler post') - }) - } - - app.wrappers = [(ctx, next) => { - wrapped.push('should not wrap pre'); - return next().then(() => { - wrapped.push('should not wrap post') - }) - }] - - app.use((ctx, next) => { - wrapped.push('middleware 1') - return next() - }, { - wrappers: [profiler] - }) - - app.use((ctx, next) => { - wrapped.push('middleware 2') - return next() - }, { wrappers: false }) - - request(app.listen()) - .get('/') - .end(() => { - wrapped.should.eql([ - 'profiler pre', - 'middleware 1', - 'middleware 2', - 'profiler post' - ]) - done(); - }); - }) - it('should handle socket errors', done => { const app = new Koa(); diff --git a/test/application/wrap.js b/test/application/wrap.js new file mode 100644 index 000000000..0a8751b73 --- /dev/null +++ b/test/application/wrap.js @@ -0,0 +1,133 @@ +'use strict'; + +const request = require('supertest'); +const assert = require('assert'); +const Koa = require('../..'); + +describe('app.wrap', () => { + it('should wrap mw correctly', done => { + const app = new Koa(); + const wrapped = [] + + app.wrappers = [(ctx, next) => { + wrapped.push('pre'); + return next().then(() => { + wrapped.push('post') + }) + }] + + app.use((ctx, next) => { + wrapped.push('middleware 1') + return next() + }) + + app.use((ctx, next) => { + wrapped.push('middleware 2') + return next() + }) + + request(app.listen()) + .get('/') + .end(() => { + wrapped.should.eql([ + 'pre', + 'middleware 1', + 'pre', + 'middleware 2', + 'post', + 'post' + ]) + done(); + }); + }) + + it ('should not wrap when mw is dewrapped', done => { + const app = new Koa(); + const wrapped = []; + + app.wrappers = [(ctx, next) => { + wrapped.push('pre'); + return next().then(() => { + wrapped.push('post'); + }); + }] + + app.use((ctx, next) => { + wrapped.push('middleware 1'); + return next(); + }).dewrap(); + + app.use((ctx, next) => { + wrapped.push('middleware 2'); + return next(); + }).dewrap(); + + request(app.listen()) + .get('/') + .end(() => { + wrapped.should.eql(['middleware 1', 'middleware 2']); + done(); + }); + }) + + it ('should not wrap when app.wrappers is false', done => { + const app = new Koa(); + const wrapped = []; + app.wrappers = false; + + app.use((ctx, next) => { + wrapped.push('middleware 1'); + return next(); + }) + + request(app.listen()) + .get('/') + .end(() => { + wrapped.should.eql(['middleware 1']); + done(); + }); + }) + + it ('app.wrap() should wrap with provided wrappers', done => { + const app = new Koa(); + const wrapped = []; + + const profiler = (ctx, next) => { + wrapped.push('profiler pre'); + return next().then(() => { + wrapped.push('profiler post'); + }); + } + + app.wrappers = [(ctx, next) => { + wrapped.push('should not wrap mw1'); + return next().then(() => { + wrapped.push('should not wrap mw1'); + }); + }] + + app.use((ctx, next) => { + wrapped.push('middleware 1') + return next(); + }).wrap([profiler]) + + app.use((ctx, next) => { + wrapped.push('middleware 2') + return next() + }) + + request(app.listen()) + .get('/') + .end(() => { + wrapped.should.eql([ + 'profiler pre', + 'middleware 1', + 'should not wrap mw1', + 'middleware 2', + 'should not wrap mw1', + 'profiler post' + ]) + done(); + }); + }) +}) From 3e3257e8737d9a6b22e303c916ee3ab35ec24520 Mon Sep 17 00:00:00 2001 From: Martin Iwanowski Date: Mon, 2 May 2016 11:21:47 +0200 Subject: [PATCH 5/6] fixed linting --- test/application/wrap.js | 59 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/test/application/wrap.js b/test/application/wrap.js index 0a8751b73..d64449959 100644 --- a/test/application/wrap.js +++ b/test/application/wrap.js @@ -1,30 +1,29 @@ 'use strict'; const request = require('supertest'); -const assert = require('assert'); const Koa = require('../..'); describe('app.wrap', () => { it('should wrap mw correctly', done => { const app = new Koa(); - const wrapped = [] + const wrapped = []; app.wrappers = [(ctx, next) => { wrapped.push('pre'); return next().then(() => { - wrapped.push('post') - }) - }] + wrapped.push('post'); + }); + }]; app.use((ctx, next) => { - wrapped.push('middleware 1') - return next() - }) + wrapped.push('middleware 1'); + return next(); + }); app.use((ctx, next) => { - wrapped.push('middleware 2') - return next() - }) + wrapped.push('middleware 2'); + return next(); + }); request(app.listen()) .get('/') @@ -36,12 +35,12 @@ describe('app.wrap', () => { 'middleware 2', 'post', 'post' - ]) + ]); done(); }); - }) + }); - it ('should not wrap when mw is dewrapped', done => { + it('should not wrap when mw is dewrapped', done => { const app = new Koa(); const wrapped = []; @@ -50,7 +49,7 @@ describe('app.wrap', () => { return next().then(() => { wrapped.push('post'); }); - }] + }]; app.use((ctx, next) => { wrapped.push('middleware 1'); @@ -68,9 +67,9 @@ describe('app.wrap', () => { wrapped.should.eql(['middleware 1', 'middleware 2']); done(); }); - }) + }); - it ('should not wrap when app.wrappers is false', done => { + it('should not wrap when app.wrappers is false', done => { const app = new Koa(); const wrapped = []; app.wrappers = false; @@ -78,7 +77,7 @@ describe('app.wrap', () => { app.use((ctx, next) => { wrapped.push('middleware 1'); return next(); - }) + }); request(app.listen()) .get('/') @@ -86,9 +85,9 @@ describe('app.wrap', () => { wrapped.should.eql(['middleware 1']); done(); }); - }) + }); - it ('app.wrap() should wrap with provided wrappers', done => { + it('app.wrap() should wrap with provided wrappers', done => { const app = new Koa(); const wrapped = []; @@ -97,24 +96,24 @@ describe('app.wrap', () => { return next().then(() => { wrapped.push('profiler post'); }); - } + }; app.wrappers = [(ctx, next) => { wrapped.push('should not wrap mw1'); return next().then(() => { wrapped.push('should not wrap mw1'); }); - }] + }]; app.use((ctx, next) => { - wrapped.push('middleware 1') + wrapped.push('middleware 1'); return next(); - }).wrap([profiler]) + }).wrap([profiler]); app.use((ctx, next) => { - wrapped.push('middleware 2') - return next() - }) + wrapped.push('middleware 2'); + return next(); + }); request(app.listen()) .get('/') @@ -126,8 +125,8 @@ describe('app.wrap', () => { 'middleware 2', 'should not wrap mw1', 'profiler post' - ]) + ]); done(); }); - }) -}) + }); +}); From 92770b2d63c66b13c0bb754ee7f6f1633efa7e62 Mon Sep 17 00:00:00 2001 From: Martin Iwanowski Date: Mon, 2 May 2016 11:22:08 +0200 Subject: [PATCH 6/6] reference PR for tests to pass --- lib/application.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/application.js b/lib/application.js index 98aeb5f29..efc9cedce 100644 --- a/lib/application.js +++ b/lib/application.js @@ -9,7 +9,7 @@ const isGeneratorFunction = require('is-generator-function'); const debug = require('debug')('koa:application'); const onFinished = require('on-finished'); const response = require('./response'); -const compose = require('../../compose'); +const compose = require('koa-compose'); const isJSON = require('koa-is-json'); const context = require('./context'); const request = require('./request'); diff --git a/package.json b/package.json index 94be43923..5b8f80e70 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "http-assert": "^1.1.0", "http-errors": "^1.2.8", "is-generator-function": "^1.0.3", - "koa-compose": "^3.0.0", + "koa-compose": "fl0w/compose#next", "koa-convert": "^1.2.0", "koa-is-json": "^1.0.0", "mime-types": "^2.0.7",