refactor Application into a class

This commit is contained in:
Tejas Manohar 2015-10-13 01:19:42 -05:00
parent e8f79d43f9
commit 93ade5e2dd
23 changed files with 243 additions and 247 deletions

View file

@ -44,8 +44,8 @@ $ npm install koa
## Example ## Example
```js ```js
const koa = require('koa'); const Koa = require('koa');
const app = koa(); const app = new Koa();
// logger // logger

View file

@ -2,8 +2,8 @@
'use strict'; 'use strict';
const http = require('http'); const http = require('http');
const koa = require('../..'); const Koa = require('../..');
const app = koa(); const app = new Koa();
app.experimental = true; app.experimental = true;

View file

@ -2,8 +2,8 @@
'use strict'; 'use strict';
const http = require('http'); const http = require('http');
const koa = require('..'); const Koa = require('..');
const app = koa(); const app = new Koa();
// number of middleware // number of middleware

View file

@ -30,7 +30,7 @@ $ node my-koa-app.js
```js ```js
var koa = require('koa'); var koa = require('koa');
var app = koa(); var app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = 'Hello World'; this.body = 'Hello World';
@ -56,7 +56,7 @@ app.listen(3000);
```js ```js
var koa = require('koa'); var koa = require('koa');
var app = koa(); var app = new Koa();
// x-response-time // x-response-time
@ -106,7 +106,7 @@ app.listen(3000);
```js ```js
var koa = require('koa'); var koa = require('koa');
var app = koa(); var app = new Koa();
app.listen(3000); app.listen(3000);
``` ```
@ -115,7 +115,7 @@ app.listen(3000);
```js ```js
var http = require('http'); var http = require('http');
var koa = require('koa'); var koa = require('koa');
var app = koa(); var app = new Koa();
http.createServer(app.callback()).listen(3000); http.createServer(app.callback()).listen(3000);
``` ```
@ -125,7 +125,7 @@ http.createServer(app.callback()).listen(3000);
```js ```js
var http = require('http'); var http = require('http');
var koa = require('koa'); var koa = require('koa');
var app = koa(); var app = new Koa();
http.createServer(app.callback()).listen(3000); http.createServer(app.callback()).listen(3000);
http.createServer(app.callback()).listen(3001); http.createServer(app.callback()).listen(3001);
``` ```

View file

@ -24,159 +24,155 @@ const only = require('only');
const co = require('co'); const co = require('co');
/** /**
* Application prototype. * Expose `Application` class.
* Inherits from `Emitter.prototype`.
*/ */
const app = Application.prototype; module.exports = class Application extends Emitter {
/** /**
* Expose `Application`. * Initialize a new `Application`.
*/ *
* @api public
*/
module.exports = Application; constructor() {
super();
/** if (!(this instanceof Application)) return new Application;
* Initialize a new `Application`. this.env = process.env.NODE_ENV || 'development';
* this.subdomainOffset = 2;
* @api public this.middleware = [];
*/ this.context = Object.create(context);
this.request = Object.create(request);
this.response = Object.create(response);
}
/**
* Shorthand for:
*
* http.createServer(app.callback()).listen(...)
*
* @param {Mixed} ...
* @return {Server}
* @api public
*/
listen() {
debug('listen');
const server = http.createServer(this.callback());
return server.listen.apply(server, arguments);
}
/**
* Return JSON representation.
* We only bother showing settings.
*
* @return {Object}
* @api public
*/
toJSON() {
return only(this, [
'subdomainOffset',
'env'
]);
}
inspect() {
return this.toJSON();
}
/**
* Use the given middleware `fn`.
*
* @param {GeneratorFunction} fn
* @return {Application} self
* @api public
*/
use(fn) {
if (!this.experimental) {
// es7 async functions are allowed
assert(fn && 'GeneratorFunction' == fn.constructor.name, 'app.use() requires a generator function');
}
debug('use %s', fn._name || fn.name || '-');
this.middleware.push(fn);
return this;
}
/**
* Return a request handler callback
* for node's native http server.
*
* @return {Function}
* @api public
*/
callback() {
const fn = this.experimental
? compose_es7(this.middleware)
: co.wrap(compose(this.middleware));
if (!this.listeners('error').length) this.on('error', this.onerror);
return (req, res) => {
res.statusCode = 404;
const ctx = this.createContext(req, res);
onFinished(res, ctx.onerror);
fn.call(ctx).then(function () {
respond.call(ctx);
}).catch(ctx.onerror);
}
}
/**
* Initialize a new context.
*
* @api private
*/
createContext(req, res) {
const context = Object.create(this.context);
const request = context.request = Object.create(this.request);
const 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;
request.response = response;
response.request = request;
context.onerror = context.onerror.bind(context);
context.originalUrl = request.originalUrl = req.url;
context.cookies = new Cookies(req, res, this.keys);
context.accept = request.accept = accepts(req);
context.state = {};
return context;
}
/**
* Default error handler.
*
* @param {Error} err
* @api private
*/
onerror(err) {
assert(err instanceof Error, `non-error thrown: ${err}`);
if (404 == err.status || err.expose) return;
if (this.silent) return;
// DEPRECATE env-specific logging in v2
if ('test' == this.env) return;
const msg = err.stack || err.toString();
console.error();
console.error(msg.replace(/^/gm, ' '));
console.error();
}
function Application() {
if (!(this instanceof Application)) return new Application;
this.env = process.env.NODE_ENV || 'development';
this.subdomainOffset = 2;
this.middleware = [];
this.context = Object.create(context);
this.request = Object.create(request);
this.response = Object.create(response);
} }
/**
* Inherit from `Emitter.prototype`.
*/
Object.setPrototypeOf(Application.prototype, Emitter.prototype);
/**
* Shorthand for:
*
* http.createServer(app.callback()).listen(...)
*
* @param {Mixed} ...
* @return {Server}
* @api public
*/
app.listen = function(){
debug('listen');
const server = http.createServer(this.callback());
return server.listen.apply(server, arguments);
};
/**
* Return JSON representation.
* We only bother showing settings.
*
* @return {Object}
* @api public
*/
app.inspect =
app.toJSON = function(){
return only(this, [
'subdomainOffset',
'env'
]);
};
/**
* Use the given middleware `fn`.
*
* @param {GeneratorFunction} fn
* @return {Application} self
* @api public
*/
app.use = function(fn){
if (!this.experimental) {
// es7 async functions are allowed
assert(fn && 'GeneratorFunction' == fn.constructor.name, 'app.use() requires a generator function');
}
debug('use %s', fn._name || fn.name || '-');
this.middleware.push(fn);
return this;
};
/**
* Return a request handler callback
* for node's native http server.
*
* @return {Function}
* @api public
*/
app.callback = function(){
const fn = this.experimental
? compose_es7(this.middleware)
: co.wrap(compose(this.middleware));
if (!this.listeners('error').length) this.on('error', this.onerror);
return (req, res) => {
res.statusCode = 404;
const ctx = this.createContext(req, res);
onFinished(res, ctx.onerror);
fn.call(ctx).then(function () {
respond.call(ctx);
}).catch(ctx.onerror);
}
};
/**
* Initialize a new context.
*
* @api private
*/
app.createContext = function(req, res){
const context = Object.create(this.context);
const request = context.request = Object.create(this.request);
const 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;
request.response = response;
response.request = request;
context.onerror = context.onerror.bind(context);
context.originalUrl = request.originalUrl = req.url;
context.cookies = new Cookies(req, res, this.keys);
context.accept = request.accept = accepts(req);
context.state = {};
return context;
};
/**
* Default error handler.
*
* @param {Error} err
* @api private
*/
app.onerror = function(err){
assert(err instanceof Error, `non-error thrown: ${err}`);
if (404 == err.status || err.expose) return;
if (this.silent) return;
// DEPRECATE env-specific logging in v2
if ('test' == this.env) return;
const msg = err.stack || err.toString();
console.error();
console.error(msg.replace(/^/gm, ' '));
console.error();
};
/** /**
* Response helper. * Response helper.
*/ */

View file

@ -3,12 +3,12 @@
const request = require('supertest'); const request = require('supertest');
const assert = require('assert'); const assert = require('assert');
const koa = require('../..'); const Koa = require('../..');
describe('app.context', function(){ describe('app.context', function(){
const app1 = koa(); const app1 = new Koa();
app1.context.msg = 'hello'; app1.context.msg = 'hello';
const app2 = koa(); const app2 = new Koa();
it('should merge properties', function(done){ it('should merge properties', function(done){
app1.use(function *(next){ app1.use(function *(next){

View file

@ -3,11 +3,11 @@
const request = require('supertest'); const request = require('supertest');
const assert = require('assert'); const assert = require('assert');
const koa = require('../..'); const Koa = require('../..');
describe('app', function(){ describe('app', function(){
it('should handle socket errors', function(done){ it('should handle socket errors', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
// triggers this.socket.writable == false // triggers this.socket.writable == false
@ -25,7 +25,7 @@ describe('app', function(){
}) })
it('should not .writeHead when !socket.writable', function(done){ it('should not .writeHead when !socket.writable', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
// set .writable to false // set .writable to false
@ -49,7 +49,7 @@ describe('app', function(){
it('should set development env when NODE_ENV missing', function(){ it('should set development env when NODE_ENV missing', function(){
const NODE_ENV = process.env.NODE_ENV; const NODE_ENV = process.env.NODE_ENV;
process.env.NODE_ENV = ''; process.env.NODE_ENV = '';
const app = koa(); const app = new Koa();
process.env.NODE_ENV = NODE_ENV; process.env.NODE_ENV = NODE_ENV;
assert.equal(app.env, 'development'); assert.equal(app.env, 'development');
}) })

View file

@ -1,11 +1,11 @@
'use strict'; 'use strict';
const koa = require('../..'); const Koa = require('../..');
describe('app.inspect()', function(){ describe('app.inspect()', function(){
it('should work', function(){ it('should work', function(){
const app = koa(); const app = new Koa();
const util = require('util'); const util = require('util');
const str = util.inspect(app); const str = util.inspect(app);
}) })

View file

@ -2,12 +2,12 @@
'use strict'; 'use strict';
const stderr = require('test-console').stderr; const stderr = require('test-console').stderr;
const koa = require('../..'); const Koa = require('../..');
const AssertionError = require('assert').AssertionError; const AssertionError = require('assert').AssertionError;
describe('app.onerror(err)', function(){ describe('app.onerror(err)', function(){
it('should throw an error if a non-error is given', function(done){ it('should throw an error if a non-error is given', function(done){
const app = koa(); const app = new Koa();
try { try {
app.onerror('foo'); app.onerror('foo');
@ -22,7 +22,7 @@ describe('app.onerror(err)', function(){
}) })
it('should do nothing if status is 404', function(done){ it('should do nothing if status is 404', function(done){
const app = koa(); const app = new Koa();
const err = new Error(); const err = new Error();
err.status = 404; err.status = 404;
@ -37,7 +37,7 @@ describe('app.onerror(err)', function(){
}) })
it('should do nothing if .silent', function(done){ it('should do nothing if .silent', function(done){
const app = koa(); const app = new Koa();
app.silent = true; app.silent = true;
const err = new Error(); const err = new Error();
@ -51,7 +51,7 @@ describe('app.onerror(err)', function(){
}) })
it('should log the error to stderr', function(done){ it('should log the error to stderr', function(done){
const app = koa(); const app = new Koa();
app.env = 'dev'; app.env = 'dev';
const err = new Error(); const err = new Error();
@ -67,7 +67,7 @@ describe('app.onerror(err)', function(){
}) })
it('should use err.toString() instad of err.stack', function(done){ it('should use err.toString() instad of err.stack', function(done){
const app = koa(); const app = new Koa();
app.env = 'dev'; app.env = 'dev';
const err = new Error('mock stack null'); const err = new Error('mock stack null');

View file

@ -3,12 +3,12 @@
const request = require('supertest'); const request = require('supertest');
const assert = require('assert'); const assert = require('assert');
const koa = require('../..'); const Koa = require('../..');
describe('app.request', function(){ describe('app.request', function(){
const app1 = koa(); const app1 = new Koa();
app1.request.message = 'hello'; app1.request.message = 'hello';
const app2 = koa(); const app2 = new Koa();
it('should merge properties', function(done){ it('should merge properties', function(done){
app1.use(function *(next){ app1.use(function *(next){

View file

@ -4,13 +4,13 @@
const request = require('supertest'); const request = require('supertest');
const statuses = require('statuses'); const statuses = require('statuses');
const assert = require('assert'); const assert = require('assert');
const koa = require('../..'); const Koa = require('../..');
const fs = require('fs'); const fs = require('fs');
describe('app.respond', function(){ describe('app.respond', function(){
describe('when this.respond === false', function(){ describe('when this.respond === false', function(){
it('should bypass app.respond', function(done){ it('should bypass app.respond', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = 'Hello'; this.body = 'Hello';
@ -36,7 +36,7 @@ describe('app.respond', function(){
describe('when HEAD is used', function(){ describe('when HEAD is used', function(){
it('should not respond with the body', function(done){ it('should not respond with the body', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = 'Hello'; this.body = 'Hello';
@ -57,7 +57,7 @@ describe('app.respond', function(){
}) })
it('should keep json headers', function(done){ it('should keep json headers', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = { hello: 'world' }; this.body = { hello: 'world' };
@ -78,7 +78,7 @@ describe('app.respond', function(){
}) })
it('should keep string headers', function(done){ it('should keep string headers', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = 'hello world'; this.body = 'hello world';
@ -99,7 +99,7 @@ describe('app.respond', function(){
}) })
it('should keep buffer headers', function(done){ it('should keep buffer headers', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = new Buffer('hello world'); this.body = new Buffer('hello world');
@ -120,7 +120,7 @@ describe('app.respond', function(){
}) })
it('should respond with a 404 if no body was set', function(done){ it('should respond with a 404 if no body was set', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
@ -134,7 +134,7 @@ describe('app.respond', function(){
}) })
it('should respond with a 200 if body = ""', function(done){ it('should respond with a 200 if body = ""', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = ''; this.body = '';
@ -148,7 +148,7 @@ describe('app.respond', function(){
}) })
it('should not overwrite the content-type', function(done){ it('should not overwrite the content-type', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 200; this.status = 200;
@ -166,7 +166,7 @@ describe('app.respond', function(){
describe('when no middleware are present', function(){ describe('when no middleware are present', function(){
it('should 404', function(done){ it('should 404', function(done){
const app = koa(); const app = new Koa();
const server = app.listen(); const server = app.listen();
@ -178,7 +178,7 @@ describe('app.respond', function(){
describe('when res has already been written to', function(){ describe('when res has already been written to', function(){
it('should not cause an app error', function(done){ it('should not cause an app error', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
const res = this.res; const res = this.res;
@ -209,7 +209,7 @@ describe('app.respond', function(){
}) })
it('should send the right body', function(done){ it('should send the right body', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
const res = this.res; const res = this.res;
@ -233,7 +233,7 @@ describe('app.respond', function(){
describe('when .body is missing', function(){ describe('when .body is missing', function(){
describe('with status=400', function(){ describe('with status=400', function(){
it('should respond with the associated status message', function(done){ it('should respond with the associated status message', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 400; this.status = 400;
@ -251,7 +251,7 @@ describe('app.respond', function(){
describe('with status=204', function(){ describe('with status=204', function(){
it('should respond without a body', function(done){ it('should respond without a body', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 204; this.status = 204;
@ -274,7 +274,7 @@ describe('app.respond', function(){
describe('with status=205', function(){ describe('with status=205', function(){
it('should respond without a body', function(done){ it('should respond without a body', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 205; this.status = 205;
@ -297,7 +297,7 @@ describe('app.respond', function(){
describe('with status=304', function(){ describe('with status=304', function(){
it('should respond without a body', function(done){ it('should respond without a body', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 304; this.status = 304;
@ -320,7 +320,7 @@ describe('app.respond', function(){
describe('with custom status=700', function(){ describe('with custom status=700', function(){
it('should respond with the associated status message', function (done){ it('should respond with the associated status message', function (done){
const app = koa(); const app = new Koa();
statuses['700'] = 'custom status'; statuses['700'] = 'custom status';
app.use(function *(){ app.use(function *(){
@ -343,7 +343,7 @@ describe('app.respond', function(){
describe('with custom statusMessage=ok', function(){ describe('with custom statusMessage=ok', function(){
it('should respond with the custom status message', function (done){ it('should respond with the custom status message', function (done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 200; this.status = 200;
@ -366,7 +366,7 @@ describe('app.respond', function(){
describe('with custom status without message', function (){ describe('with custom status without message', function (){
it('should respond with the status code number', function (done){ it('should respond with the status code number', function (done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.res.statusCode = 701; this.res.statusCode = 701;
@ -384,7 +384,7 @@ describe('app.respond', function(){
describe('when .body is a null', function(){ describe('when .body is a null', function(){
it('should respond 204 by default', function(done){ it('should respond 204 by default', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = null; this.body = null;
@ -405,7 +405,7 @@ describe('app.respond', function(){
}) })
it('should respond 204 with status=200', function(done){ it('should respond 204 with status=200', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 200; this.status = 200;
@ -427,7 +427,7 @@ describe('app.respond', function(){
}) })
it('should respond 205 with status=205', function(done){ it('should respond 205 with status=205', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 205; this.status = 205;
@ -449,7 +449,7 @@ describe('app.respond', function(){
}) })
it('should respond 304 with status=304', function(done){ it('should respond 304 with status=304', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 304; this.status = 304;
@ -473,7 +473,7 @@ describe('app.respond', function(){
describe('when .body is a string', function(){ describe('when .body is a string', function(){
it('should respond', function(done){ it('should respond', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = 'Hello'; this.body = 'Hello';
@ -489,7 +489,7 @@ describe('app.respond', function(){
describe('when .body is a Buffer', function(){ describe('when .body is a Buffer', function(){
it('should respond', function(done){ it('should respond', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = new Buffer('Hello'); this.body = new Buffer('Hello');
@ -505,7 +505,7 @@ describe('app.respond', function(){
describe('when .body is a Stream', function(){ describe('when .body is a Stream', function(){
it('should respond', function(done){ it('should respond', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = fs.createReadStream('package.json'); this.body = fs.createReadStream('package.json');
@ -527,7 +527,7 @@ describe('app.respond', function(){
}) })
it('should strip content-length when overwriting', function(done){ it('should strip content-length when overwriting', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = 'hello'; this.body = 'hello';
@ -550,7 +550,7 @@ describe('app.respond', function(){
}) })
it('should keep content-length if not overwritten', function(done){ it('should keep content-length if not overwritten', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.length = fs.readFileSync('package.json').length; this.length = fs.readFileSync('package.json').length;
@ -573,7 +573,7 @@ describe('app.respond', function(){
}) })
it('should keep content-length if overwritten with the same stream', function(done){ it('should keep content-length if overwritten with the same stream', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.length = fs.readFileSync('package.json').length; this.length = fs.readFileSync('package.json').length;
@ -598,7 +598,7 @@ describe('app.respond', function(){
}) })
it('should handle errors', function(done){ it('should handle errors', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.set('Content-Type', 'application/json; charset=utf-8'); this.set('Content-Type', 'application/json; charset=utf-8');
@ -615,7 +615,7 @@ describe('app.respond', function(){
}) })
it('should handle errors when no content status', function(done){ it('should handle errors when no content status', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 204; this.status = 204;
@ -631,7 +631,7 @@ describe('app.respond', function(){
it('should handle all intermediate stream body errors', function(done){ it('should handle all intermediate stream body errors', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = fs.createReadStream('does not exist'); this.body = fs.createReadStream('does not exist');
@ -649,7 +649,7 @@ describe('app.respond', function(){
describe('when .body is an Object', function(){ describe('when .body is an Object', function(){
it('should respond with json', function(done){ it('should respond with json', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = { hello: 'world' }; this.body = { hello: 'world' };
@ -666,7 +666,7 @@ describe('app.respond', function(){
describe('when an error occurs', function(){ describe('when an error occurs', function(){
it('should emit "error" on the app', function(done){ it('should emit "error" on the app', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
throw new Error('boom'); throw new Error('boom');
@ -684,7 +684,7 @@ describe('app.respond', function(){
describe('with an .expose property', function(){ describe('with an .expose property', function(){
it('should expose the message', function(done){ it('should expose the message', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
const err = new Error('sorry!'); const err = new Error('sorry!');
@ -702,7 +702,7 @@ describe('app.respond', function(){
describe('with a .status property', function(){ describe('with a .status property', function(){
it('should respond with .status', function(done){ it('should respond with .status', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
const err = new Error('s3 explodes'); const err = new Error('s3 explodes');
@ -718,7 +718,7 @@ describe('app.respond', function(){
}) })
it('should respond with 500', function(done){ it('should respond with 500', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
throw new Error('boom!'); throw new Error('boom!');
@ -733,7 +733,7 @@ describe('app.respond', function(){
}) })
it('should be catchable', function(done){ it('should be catchable', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
try { try {
@ -760,7 +760,7 @@ describe('app.respond', function(){
describe('when status and body property', function(){ describe('when status and body property', function(){
it('should 200', function(done){ it('should 200', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 304; this.status = 304;
@ -777,7 +777,7 @@ describe('app.respond', function(){
}) })
it('should 204', function(done) { it('should 204', function(done) {
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = 200; this.status = 200;

View file

@ -3,12 +3,12 @@
const request = require('supertest'); const request = require('supertest');
const assert = require('assert'); const assert = require('assert');
const koa = require('../..'); const Koa = require('../..');
describe('app.response', function(){ describe('app.response', function(){
const app1 = koa(); const app1 = new Koa();
app1.response.msg = 'hello'; app1.response.msg = 'hello';
const app2 = koa(); const app2 = new Koa();
it('should merge properties', function(done){ it('should merge properties', function(done){
app1.use(function *(next){ app1.use(function *(next){

View file

@ -1,11 +1,11 @@
'use strict'; 'use strict';
const koa = require('../..'); const Koa = require('../..');
describe('app.toJSON()', function(){ describe('app.toJSON()', function(){
it('should work', function(){ it('should work', function(){
const app = koa(); const app = new Koa();
const obj = app.toJSON(); const obj = app.toJSON();
obj.should.eql({ obj.should.eql({

View file

@ -2,11 +2,11 @@
'use strict'; 'use strict';
const request = require('supertest'); const request = require('supertest');
const koa = require('../..'); const Koa = require('../..');
describe('app.use(fn)', function(){ describe('app.use(fn)', function(){
it('should compose middleware', function(done){ it('should compose middleware', function(done){
const app = koa(); const app = new Koa();
const calls = []; const calls = [];
app.use(function *(next){ app.use(function *(next){
@ -40,7 +40,7 @@ describe('app.use(fn)', function(){
}) })
it('should error when a non-generator function is passed', function(){ it('should error when a non-generator function is passed', function(){
const app = koa(); const app = new Koa();
try { try {
app.use(function(){}); app.use(function(){});
@ -50,7 +50,7 @@ describe('app.use(fn)', function(){
}) })
it('should not error when a non-generator function is passed when .experimental=true', function(){ it('should not error when a non-generator function is passed when .experimental=true', function(){
const app = koa(); const app = new Koa();
app.experimental = true; app.experimental = true;
app.use(function(){}); app.use(function(){});
}) })

View file

@ -2,11 +2,11 @@
'use strict'; 'use strict';
const request = require('supertest'); const request = require('supertest');
const koa = require('../..'); const Koa = require('../..');
describe('ctx.cookies.set()', function(){ describe('ctx.cookies.set()', function(){
it('should set an unsigned cookie', function(done){ it('should set an unsigned cookie', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
this.cookies.set('name', 'jon'); this.cookies.set('name', 'jon');
@ -32,7 +32,7 @@ describe('ctx.cookies.set()', function(){
describe('with .signed', function(){ describe('with .signed', function(){
describe('when no .keys are set', function(){ describe('when no .keys are set', function(){
it('should error', function(done){ it('should error', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
try { try {
@ -49,7 +49,7 @@ describe('ctx.cookies.set()', function(){
}) })
it('should send a signed cookie', function(done){ it('should send a signed cookie', function(done){
const app = koa(); const app = new Koa();
app.keys = ['a', 'b']; app.keys = ['a', 'b'];

View file

@ -2,11 +2,11 @@
'use strict'; 'use strict';
const request = require('supertest'); const request = require('supertest');
const koa = require('../..'); const Koa = require('../..');
describe('ctx.onerror(err)', function(){ describe('ctx.onerror(err)', function(){
it('should respond', function(done){ it('should respond', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
this.body = 'something else'; this.body = 'something else';
@ -25,7 +25,7 @@ describe('ctx.onerror(err)', function(){
}) })
it('should unset all headers', function(done){ it('should unset all headers', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
this.set('Vary', 'Accept-Encoding'); this.set('Vary', 'Accept-Encoding');
@ -55,7 +55,7 @@ describe('ctx.onerror(err)', function(){
describe('when invalid err.status', function(){ describe('when invalid err.status', function(){
describe('not number', function(){ describe('not number', function(){
it('should respond 500', function(done){ it('should respond 500', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
this.body = 'something else'; this.body = 'something else';
@ -76,7 +76,7 @@ describe('ctx.onerror(err)', function(){
describe('not http status code', function(){ describe('not http status code', function(){
it('should respond 500', function(done){ it('should respond 500', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
this.body = 'something else'; this.body = 'something else';
@ -98,7 +98,7 @@ describe('ctx.onerror(err)', function(){
describe('when non-error thrown', function(){ describe('when non-error thrown', function(){
it('should response non-error thrown message', function(done){ it('should response non-error thrown message', function(done){
const app = koa(); const app = new Koa();
app.use(function *(next){ app.use(function *(next){
throw 'string error'; throw 'string error';

View file

@ -3,11 +3,11 @@
const request = require('supertest'); const request = require('supertest');
const assert = require('assert'); const assert = require('assert');
const koa = require('../..'); const Koa = require('../..');
describe('ctx.state', function() { describe('ctx.state', function() {
it('should provide a ctx.state namespace', function(done) { it('should provide a ctx.state namespace', function(done) {
const app = koa(); const app = new Koa();
app.use(function *() { app.use(function *() {
assert.deepEqual(this.state, {}); assert.deepEqual(this.state, {});

View file

@ -6,11 +6,11 @@
*/ */
const request = require('supertest'); const request = require('supertest');
const koa = require('../..'); const Koa = require('../..');
describe('.experimental=true', function () { describe('.experimental=true', function () {
it('should support async functions', function (done) { it('should support async functions', function (done) {
const app = koa(); const app = new Koa();
app.experimental = true; app.experimental = true;
app.use(async function (next) { app.use(async function (next) {
const string = await Promise.resolve('asdf'); const string = await Promise.resolve('asdf');

View file

@ -2,7 +2,7 @@
'use strict'; 'use strict';
const Stream = require('stream'); const Stream = require('stream');
const koa = require('../..'); const Koa = require('../..');
exports = module.exports = function(req, res){ exports = module.exports = function(req, res){
const socket = new Stream.Duplex(); const socket = new Stream.Duplex();
@ -11,7 +11,7 @@ exports = module.exports = function(req, res){
res.getHeader = function(k){ return res._headers[k.toLowerCase()] }; res.getHeader = function(k){ return res._headers[k.toLowerCase()] };
res.setHeader = function(k, v){ res._headers[k.toLowerCase()] = v }; res.setHeader = function(k, v){ res._headers[k.toLowerCase()] = v };
res.removeHeader = function(k, v){ delete res._headers[k.toLowerCase()] }; res.removeHeader = function(k, v){ delete res._headers[k.toLowerCase()] };
return koa().createContext(req, res); return (new Koa()).createContext(req, res);
} }
exports.request = function(req, res){ exports.request = function(req, res){

View file

@ -3,7 +3,7 @@
const Stream = require('stream'); const Stream = require('stream');
const http = require('http'); const http = require('http');
const koa = require('../../'); const Koa = require('../../');
const context = require('../helpers/context'); const context = require('../helpers/context');
describe('ctx.href', function(){ describe('ctx.href', function(){
@ -25,7 +25,7 @@ describe('ctx.href', function(){
}) })
it('should work with `GET http://example.com/foo`', function(done){ it('should work with `GET http://example.com/foo`', function(done){
const app = koa() const app = new Koa()
app.use(function* (){ app.use(function* (){
this.body = this.href this.body = this.href
}) })

View file

@ -3,7 +3,7 @@
const Stream = require('stream'); const Stream = require('stream');
const http = require('http'); const http = require('http');
const koa = require('../../'); const Koa = require('../../');
const context = require('../helpers/context'); const context = require('../helpers/context');
describe('ctx.origin', function(){ describe('ctx.origin', function(){

View file

@ -3,7 +3,7 @@
const context = require('../helpers/context'); const context = require('../helpers/context');
const request = require('supertest'); const request = require('supertest');
const koa = require('../..'); const Koa = require('../..');
describe('ctx.attachment([filename])', function(){ describe('ctx.attachment([filename])', function(){
describe('when given a filename', function(){ describe('when given a filename', function(){
@ -32,7 +32,7 @@ describe('ctx.attachment([filename])', function(){
}) })
it('should work with http client', function(done){ it('should work with http client', function(done){
const app = koa(); const app = new Koa();
app.use(function* (next){ app.use(function* (next){
this.attachment('path/to/include-no-ascii-char-中文名-ok.json') this.attachment('path/to/include-no-ascii-char-中文名-ok.json')

View file

@ -5,7 +5,7 @@ const response = require('../helpers/context').response;
const request = require('supertest'); const request = require('supertest');
const statuses = require('statuses'); const statuses = require('statuses');
const assert = require('assert'); const assert = require('assert');
const koa = require('../..'); const Koa = require('../..');
describe('res.status=', function(){ describe('res.status=', function(){
describe('when a status code', function(){ describe('when a status code', function(){
@ -60,7 +60,7 @@ describe('res.status=', function(){
function strip(status) { function strip(status) {
it('should strip content related header fields', function(done){ it('should strip content related header fields', function(done){
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.body = { foo: 'bar' }; this.body = { foo: 'bar' };
@ -86,7 +86,7 @@ describe('res.status=', function(){
}) })
it('should strip content releated header fields after status set', function(done) { it('should strip content releated header fields after status set', function(done) {
const app = koa(); const app = new Koa();
app.use(function *(){ app.use(function *(){
this.status = status; this.status = status;