From 0be144211189c0ebd2ca059d7f1ee2e72b2ac6b9 Mon Sep 17 00:00:00 2001 From: Jonathan Ong Date: Wed, 13 Nov 2013 18:34:15 -0800 Subject: [PATCH 1/2] expose app-specific prototypes, cleanup/fix tests --- lib/application.js | 29 +++++++++++++++++++++++++++-- lib/context.js | 26 ++------------------------ lib/request.js | 21 +-------------------- lib/response.js | 19 +------------------ test/context.js | 24 ++++++++++++++++-------- test/request.js | 18 ------------------ test/request/header.js | 2 +- test/request/host.js | 2 +- test/request/protocol.js | 2 +- test/request/secure.js | 2 +- test/response.js | 18 ------------------ test/response/body.js | 2 +- test/response/header.js | 2 +- test/response/length.js | 2 +- test/response/status.js | 2 +- 15 files changed, 55 insertions(+), 116 deletions(-) delete mode 100644 test/request.js delete mode 100644 test/response.js diff --git a/lib/application.js b/lib/application.js index d511ff5..b21c30c 100644 --- a/lib/application.js +++ b/lib/application.js @@ -6,7 +6,10 @@ var debug = require('debug')('koa:application'); var Emitter = require('events').EventEmitter; var compose = require('koa-compose'); -var Context = require('./context'); +var context = require('./context'); +var request = require('./request'); +var response = require('./response'); +var Cookies = require('cookies'); var Stream = require('stream'); var http = require('http'); var co = require('co'); @@ -38,6 +41,9 @@ function Application() { this.poweredBy = true; this.jsonSpaces = 2; this.middleware = []; + this.context = Object.create(context); + this.request = Object.create(request); + this.response = Object.create(response); } /** @@ -89,12 +95,31 @@ app.callback = function(){ var self = this; return function(req, res, next){ - var ctx = new Context(self, req, res); + var ctx = self.createContext(req, res); co.call(ctx, gen)(next || ctx.onerror); } }; +/** + * Initialize a new context. + * + * @api private + */ + +app.createContext = function(req, res){ + var context = Object.create(this.context); + var request = context.request = Object.create(this.request); + var response = context.response = Object.create(this.response); + context.app = request.app = response.app = this; + context.req = request.req = response.req = req; + context.res = request.res = response.res = res; + request.ctx = response.ctx = context; + context.onerror = context.onerror.bind(context); + context.cookies = new Cookies(req, res); + return context; +} + /** * Default error handler. * diff --git a/lib/context.js b/lib/context.js index 5d25ffb..1181bc5 100644 --- a/lib/context.js +++ b/lib/context.js @@ -9,33 +9,11 @@ var Response = require('./response'); var Cookies = require('cookies'); var http = require('http'); -/** - * Expose `Context`. - */ - -module.exports = Context; - -/** - * Initialie a new Context. - * - * @api private - */ - -function Context(app, req, res){ - this.onerror = this.onerror.bind(this); - this.cookies = new Cookies(req, res); - this.app = app; - this.req = req; - this.res = res; - this.request = new Request(this); - this.response = new Response(this); -} - /** * Prototype. */ -Context.prototype = { +module.exports = { /** * Delegate to Request#header. @@ -365,7 +343,7 @@ Context.prototype = { attachment: function() { return this.response.attachment.apply(this.response, arguments); - }, + }, /** * Throw an error with `msg` and optional `status` diff --git a/lib/request.js b/lib/request.js index 911009f..56ecd8e 100644 --- a/lib/request.js +++ b/lib/request.js @@ -6,7 +6,6 @@ var debug = require('debug')('koa:context'); var Negotiator = require('negotiator'); var statuses = require('./status'); -var Cookies = require('cookies'); var qs = require('querystring'); var Stream = require('stream'); var fresh = require('fresh'); @@ -19,29 +18,11 @@ var url = require('url'); var parse = url.parse; var stringify = url.format; -/** - * Expose `Request`. - */ - -module.exports = Request; - -/** - * Initialize a new Request. - * - * @api private - */ - -function Request(ctx){ - this.app = ctx.app; - this.req = ctx.req; - this.ctx = ctx; -} - /** * Prototype. */ -Request.prototype = { +module.exports = { /** * Return request header. diff --git a/lib/response.js b/lib/response.js index a63245d..3147a87 100644 --- a/lib/response.js +++ b/lib/response.js @@ -19,28 +19,11 @@ var url = require('url'); var parse = url.parse; var stringify = url.format; -/** - * Expose `Response`. - */ - -module.exports = Response; - -/** - * Initialize a new Response. - * - * @api private - */ - -function Response(ctx){ - this.res = ctx.res; - this.ctx = ctx; -} - /** * Prototype. */ -Response.prototype = { +module.exports = { /** * Return the request socket. diff --git a/test/context.js b/test/context.js index 2494012..27e2d59 100644 --- a/test/context.js +++ b/test/context.js @@ -1,16 +1,24 @@ -var Context = require('../lib/context'); -var request = require('supertest'); -var assert = require('assert'); +var context = require('../lib/context'); +var request = require('../lib/request'); +var response = require('../lib/response'); var koa = require('..'); -var fs = require('fs'); -function context(req, res) { +exports = module.exports = function(req, res){ req = req || { headers: {} }; res = res || { _headers: {} }; res.setHeader = function(k, v){ res._headers[k.toLowerCase()] = v }; - var ctx = new Context({}, req, res); - return ctx; + return koa().createContext(req, res); } -module.exports = context; \ No newline at end of file +exports.context = function(req, res){ + return exports(req, res); +} + +exports.request = function(req, res){ + return exports(req, res).request; +} + +exports.response = function(req, res){ + return exports(req, res).response; +} \ No newline at end of file diff --git a/test/request.js b/test/request.js deleted file mode 100644 index 1aeaa0b..0000000 --- a/test/request.js +++ /dev/null @@ -1,18 +0,0 @@ - -var Context = require('../lib/context'); -var Request = require('../lib/request'); -var koa = require('..'); - -function context(req, res) { - req = req || { headers: {} }; - res = res || { _headers: {} }; - res.setHeader = function(k, v){ res._headers[k.toLowerCase()] = v }; - var ctx = new Context({}, req, res); - return ctx; -} - -function request(req, res) { - return new Request(context(req, res)); -} - -module.exports = request; \ No newline at end of file diff --git a/test/request/header.js b/test/request/header.js index 3181c5b..4ec024e 100644 --- a/test/request/header.js +++ b/test/request/header.js @@ -1,5 +1,5 @@ -var request = require('../request'); +var request = require('../context').request; describe('req.header', function(){ it('should return the request header object', function(){ diff --git a/test/request/host.js b/test/request/host.js index 714349f..5c80303 100644 --- a/test/request/host.js +++ b/test/request/host.js @@ -1,5 +1,5 @@ -var request = require('../request'); +var request = require('../context').request; describe('req.host', function(){ it('should return host void of port', function(){ diff --git a/test/request/protocol.js b/test/request/protocol.js index baa07dd..341ae57 100644 --- a/test/request/protocol.js +++ b/test/request/protocol.js @@ -1,5 +1,5 @@ -var request = require('../request'); +var request = require('../context').request; describe('req.protocol', function(){ describe('when encrypted', function(){ diff --git a/test/request/secure.js b/test/request/secure.js index 72ffa9d..fceef19 100644 --- a/test/request/secure.js +++ b/test/request/secure.js @@ -1,5 +1,5 @@ -var request = require('../request'); +var request = require('../context').request; describe('req.secure', function(){ it('should return true when encrypted', function(){ diff --git a/test/response.js b/test/response.js deleted file mode 100644 index 55e3f0d..0000000 --- a/test/response.js +++ /dev/null @@ -1,18 +0,0 @@ - -var Context = require('../lib/context'); -var Response = require('../lib/response'); -var koa = require('..'); - -function context(req, res) { - req = req || { headers: {} }; - res = res || { _headers: {} }; - res.setHeader = function(k, v){ res._headers[k.toLowerCase()] = v }; - var ctx = new Context({}, req, res); - return ctx; -} - -function response(req, res) { - return new Response(context(req, res)); -} - -module.exports = response; \ No newline at end of file diff --git a/test/response/body.js b/test/response/body.js index 39be34a..3a61f14 100644 --- a/test/response/body.js +++ b/test/response/body.js @@ -1,5 +1,5 @@ -var response = require('../response'); +var response = require('../context').response; var assert = require('assert'); var fs = require('fs'); diff --git a/test/response/header.js b/test/response/header.js index 2d71e9b..d75882c 100644 --- a/test/response/header.js +++ b/test/response/header.js @@ -1,5 +1,5 @@ -var response = require('../response'); +var response = require('../context').response; describe('res.header', function(){ it('should return the response header object', function(){ diff --git a/test/response/length.js b/test/response/length.js index a810bb0..53adba1 100644 --- a/test/response/length.js +++ b/test/response/length.js @@ -1,5 +1,5 @@ -var response = require('../response'); +var response = require('../context').response; var assert = require('assert'); describe('res.length', function(){ diff --git a/test/response/status.js b/test/response/status.js index 67b1ca5..b81f8e3 100644 --- a/test/response/status.js +++ b/test/response/status.js @@ -1,5 +1,5 @@ -var response = require('../response'); +var response = require('../context').response; var request = require('supertest'); var assert = require('assert'); var koa = require('../..'); From e6cd31ce2f4fc01435cdb7a846d0df578c0d20d0 Mon Sep 17 00:00:00 2001 From: Jonathan Ong Date: Wed, 13 Nov 2013 18:41:01 -0800 Subject: [PATCH 2/2] add tests for exposing app-specific prototypes --- test/application.js | 84 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test/application.js b/test/application.js index a9acf3c..3915d1a 100644 --- a/test/application.js +++ b/test/application.js @@ -295,3 +295,87 @@ describe('app.respond', function(){ }) }) }) + +describe('app.context', function(){ + var app1 = koa(); + app1.context.message = 'hello'; + var app2 = koa(); + + it('should merge properties', function(){ + app1.use(function *(next){ + assert.equal(this.message, 'hello') + this.status = 204 + }); + + request(app1.listen()) + .get('/') + .expect(204); + }) + + it('should not affect the original prototype', function(){ + app2.use(function *(next){ + assert.equal(this.message, undefined) + this.status = 204; + }); + + request(app2.listen()) + .get('/') + .expect(204); + }) +}) + +describe('app.request', function(){ + var app1 = koa(); + app1.request.message = 'hello'; + var app2 = koa(); + + it('should merge properties', function(){ + app1.use(function *(next){ + assert.equal(this.request.message, 'hello') + this.status = 204 + }); + + request(app1.listen()) + .get('/') + .expect(204); + }) + + it('should not affect the original prototype', function(){ + app2.use(function *(next){ + assert.equal(this.request.message, undefined) + this.status = 204; + }); + + request(app2.listen()) + .get('/') + .expect(204); + }) +}) + +describe('app.response', function(){ + var app1 = koa(); + app1.response.message = 'hello'; + var app2 = koa(); + + it('should merge properties', function(){ + app1.use(function *(next){ + assert.equal(this.response.message, 'hello') + this.status = 204 + }); + + request(app1.listen()) + .get('/') + .expect(204); + }) + + it('should not affect the original prototype', function(){ + app2.use(function *(next){ + assert.equal(this.response.message, undefined) + this.status = 204; + }); + + request(app2.listen()) + .get('/') + .expect(204); + }) +}) \ No newline at end of file