Merge pull request #85 from koajs/expose-proto

Expose proto
This commit is contained in:
TJ Holowaychuk 2013-11-14 11:23:10 -08:00
commit 64fa0b5c2a
16 changed files with 139 additions and 116 deletions

View file

@ -6,7 +6,10 @@
var debug = require('debug')('koa:application'); var debug = require('debug')('koa:application');
var Emitter = require('events').EventEmitter; var Emitter = require('events').EventEmitter;
var compose = require('koa-compose'); 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 Stream = require('stream');
var http = require('http'); var http = require('http');
var co = require('co'); var co = require('co');
@ -38,6 +41,9 @@ function Application() {
this.poweredBy = true; this.poweredBy = true;
this.jsonSpaces = 2; this.jsonSpaces = 2;
this.middleware = []; 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; var self = this;
return function(req, res, next){ 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); 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. * Default error handler.
* *

View file

@ -9,33 +9,11 @@ var Response = require('./response');
var Cookies = require('cookies'); var Cookies = require('cookies');
var http = require('http'); 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. * Prototype.
*/ */
Context.prototype = { module.exports = {
/** /**
* Delegate to Request#header. * Delegate to Request#header.

View file

@ -6,7 +6,6 @@
var debug = require('debug')('koa:context'); var debug = require('debug')('koa:context');
var Negotiator = require('negotiator'); var Negotiator = require('negotiator');
var statuses = require('./status'); var statuses = require('./status');
var Cookies = require('cookies');
var qs = require('querystring'); var qs = require('querystring');
var Stream = require('stream'); var Stream = require('stream');
var fresh = require('fresh'); var fresh = require('fresh');
@ -19,29 +18,11 @@ var url = require('url');
var parse = url.parse; var parse = url.parse;
var stringify = url.format; 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. * Prototype.
*/ */
Request.prototype = { module.exports = {
/** /**
* Return request header. * Return request header.

View file

@ -19,28 +19,11 @@ var url = require('url');
var parse = url.parse; var parse = url.parse;
var stringify = url.format; 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. * Prototype.
*/ */
Response.prototype = { module.exports = {
/** /**
* Return the request socket. * Return the request socket.

View file

@ -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);
})
})

View file

@ -1,16 +1,24 @@
var Context = require('../lib/context'); var context = require('../lib/context');
var request = require('supertest'); var request = require('../lib/request');
var assert = require('assert'); var response = require('../lib/response');
var koa = require('..'); var koa = require('..');
var fs = require('fs');
function context(req, res) { exports = module.exports = function(req, res){
req = req || { headers: {} }; req = req || { headers: {} };
res = res || { _headers: {} }; res = res || { _headers: {} };
res.setHeader = function(k, v){ res._headers[k.toLowerCase()] = v }; res.setHeader = function(k, v){ res._headers[k.toLowerCase()] = v };
var ctx = new Context({}, req, res); return koa().createContext(req, res);
return ctx;
} }
module.exports = context; 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;
}

View file

@ -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;

View file

@ -1,5 +1,5 @@
var request = require('../request'); var request = require('../context').request;
describe('req.header', function(){ describe('req.header', function(){
it('should return the request header object', function(){ it('should return the request header object', function(){

View file

@ -1,5 +1,5 @@
var request = require('../request'); var request = require('../context').request;
describe('req.host', function(){ describe('req.host', function(){
it('should return host void of port', function(){ it('should return host void of port', function(){

View file

@ -1,5 +1,5 @@
var request = require('../request'); var request = require('../context').request;
describe('req.protocol', function(){ describe('req.protocol', function(){
describe('when encrypted', function(){ describe('when encrypted', function(){

View file

@ -1,5 +1,5 @@
var request = require('../request'); var request = require('../context').request;
describe('req.secure', function(){ describe('req.secure', function(){
it('should return true when encrypted', function(){ it('should return true when encrypted', function(){

View file

@ -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;

View file

@ -1,5 +1,5 @@
var response = require('../response'); var response = require('../context').response;
var assert = require('assert'); var assert = require('assert');
var fs = require('fs'); var fs = require('fs');

View file

@ -1,5 +1,5 @@
var response = require('../response'); var response = require('../context').response;
describe('res.header', function(){ describe('res.header', function(){
it('should return the response header object', function(){ it('should return the response header object', function(){

View file

@ -1,5 +1,5 @@
var response = require('../response'); var response = require('../context').response;
var assert = require('assert'); var assert = require('assert');
describe('res.length', function(){ describe('res.length', function(){

View file

@ -1,5 +1,5 @@
var response = require('../response'); var response = require('../context').response;
var request = require('supertest'); var request = require('supertest');
var assert = require('assert'); var assert = require('assert');
var koa = require('../..'); var koa = require('../..');