Compare commits

...

24 Commits

Author SHA1 Message Date
Douglas Christopher Wilson
86328767fe 3.19.2 2015-02-01 15:15:53 -05:00
Douglas Christopher Wilson
e497d068a1 deps: marked@0.3.3 2015-02-01 14:58:19 -05:00
Douglas Christopher Wilson
926a71f5ac deps: should@~4.6.2 2015-02-01 14:56:18 -05:00
Douglas Christopher Wilson
55f5a2dc8d deps: proxy-addr@~1.0.6 2015-02-01 14:55:42 -05:00
Douglas Christopher Wilson
fe435e497e deps: connect@2.28.3 2015-02-01 14:54:46 -05:00
Douglas Christopher Wilson
0c567b3282 3.19.1 2015-01-21 03:18:16 -05:00
Douglas Christopher Wilson
855176b633 tests: remove more mocking uses 2015-01-21 03:17:30 -05:00
Douglas Christopher Wilson
b95f2ee820 deps: should@~4.6.1 2015-01-21 02:14:27 -05:00
Douglas Christopher Wilson
ae92db98f3 deps: ejs@2.1.4 2015-01-21 02:13:17 -05:00
Douglas Christopher Wilson
0b25547ca0 deps: send@0.11.1 2015-01-21 02:05:03 -05:00
Douglas Christopher Wilson
548f2865e2 deps: connect@2.28.2 2015-01-21 02:03:28 -05:00
Douglas Christopher Wilson
ee3f2b073c 3.19.0 2015-01-09 01:07:12 -05:00
Douglas Christopher Wilson
34b6385dc3 deps: debug@~2.1.1 2015-01-09 01:05:41 -05:00
Douglas Christopher Wilson
11529a2ea0 Fix OPTIONS responses to include the HEAD method property
fixes #2459
2015-01-08 23:30:42 -05:00
Douglas Christopher Wilson
b0f8809e3d deps: commander@2.6.0 2015-01-08 22:23:04 -05:00
Douglas Christopher Wilson
ec1175daa3 Use readline for prompt in express(1) 2015-01-08 22:21:50 -05:00
Douglas Christopher Wilson
3a1d9b8289 deps: ejs@2.0.8 2015-01-08 22:17:19 -05:00
Douglas Christopher Wilson
192be8fea3 deps: send@0.11.0 2015-01-08 22:15:53 -05:00
Douglas Christopher Wilson
1afcff955b deps: proxy-addr@~1.0.5 2015-01-08 22:14:46 -05:00
Douglas Christopher Wilson
224fe05697 deps: methods@~1.1.1 2015-01-08 21:31:32 -05:00
Douglas Christopher Wilson
2dd332b491 deps: mocha@~2.1.0 2015-01-08 21:25:17 -05:00
Douglas Christopher Wilson
33e4193f45 deps: should@~4.4.4 2015-01-08 21:24:28 -05:00
Douglas Christopher Wilson
c163d2f33d deps: connect@2.28.1 2015-01-08 21:18:56 -05:00
Douglas Christopher Wilson
a715ba6be4 docs: Gittip is now Gratipay 2015-01-08 17:06:08 -05:00
13 changed files with 273 additions and 114 deletions

View File

@@ -1,3 +1,56 @@
3.19.2 / 2015-02-01
===================
* deps: connect@2.28.3
- deps: compression@~1.3.1
- deps: csurf@~1.6.6
- deps: errorhandler@~1.3.3
- deps: express-session@~1.10.2
- deps: serve-index@~1.6.1
- deps: type-is@~1.5.6
* deps: proxy-addr@~1.0.6
- deps: ipaddr.js@0.1.8
3.19.1 / 2015-01-20
===================
* deps: connect@2.28.2
- deps: body-parser@~1.10.2
- deps: serve-static@~1.8.1
* deps: send@0.11.1
- Fix root path disclosure
3.19.0 / 2015-01-09
===================
* Fix `OPTIONS` responses to include the `HEAD` method property
* Use `readline` for prompt in `express(1)`
* deps: commander@2.6.0
* deps: connect@2.28.1
- deps: body-parser@~1.10.1
- deps: compression@~1.3.0
- deps: connect-timeout@~1.5.0
- deps: csurf@~1.6.4
- deps: debug@~2.1.1
- deps: errorhandler@~1.3.2
- deps: express-session@~1.10.1
- deps: finalhandler@0.3.3
- deps: method-override@~2.3.1
- deps: morgan@~1.5.1
- deps: serve-favicon@~2.2.0
- deps: serve-index@~1.6.0
- deps: serve-static@~1.8.0
- deps: type-is@~1.5.5
* deps: debug@~2.1.1
* deps: methods@~1.1.1
* deps: proxy-addr@~1.0.5
- deps: ipaddr.js@0.1.6
* deps: send@0.11.0
- deps: debug@~2.1.1
- deps: etag@~1.5.1
- deps: ms@0.7.0
- deps: on-finished@~2.2.0
3.18.6 / 2014-12-12
===================

View File

@@ -5,7 +5,7 @@
[![NPM version](https://img.shields.io/npm/v/express.svg?style=flat)](https://www.npmjs.org/package/express)
[![Build Status](https://img.shields.io/travis/strongloop/express.svg?style=flat)](https://travis-ci.org/strongloop/express)
[![Coverage Status](https://img.shields.io/coveralls/strongloop/express.svg?style=flat)](https://coveralls.io/r/strongloop/express)
[![Gittip](https://img.shields.io/gittip/dougwilson.svg?style=flat)](https://www.gittip.com/dougwilson/)
[![Gratipay](https://img.shields.io/gratipay/dougwilson.svg?style=flat)](https://gratipay.com/dougwilson/)
```js
var express = require('express');

View File

@@ -7,6 +7,7 @@
var program = require('commander')
, mkdirp = require('mkdirp')
, pkg = require('../package.json')
, readline = require('readline')
, version = pkg.version
, os = require('os')
, fs = require('fs');
@@ -249,7 +250,7 @@ var app = [
if (empty || program.force) {
createApplicationAt(path);
} else {
program.confirm('destination is not empty, continue? ', function(ok){
confirm('destination is not empty, continue? [y/N] ', function (ok) {
if (ok) {
process.stdin.destroy();
createApplicationAt(path);
@@ -261,6 +262,22 @@ var app = [
});
})(path);
/**
* Prompt for confirmation on STDOUT/STDIN
*/
function confirm(msg, callback) {
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question(msg, function (input) {
rl.close();
callback(/^y|yes|ok|true$/i.test(input));
});
}
/**
* Create application at the given directory `path`.
*

View File

@@ -196,17 +196,32 @@ Router.prototype._options = function(req, res, next){
* @api private
*/
Router.prototype._optionsFor = function(path){
var self = this;
return methods.filter(function(method){
var routes = self.map[method];
if (!routes || 'options' == method) return;
for (var i = 0, len = routes.length; i < len; ++i) {
if (routes[i].match(path)) return true;
Router.prototype._optionsFor = function _optionsFor(path) {
var options = [];
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
if (method === 'options') continue;
var routes = this.map[method];
// HEAD methods include GET routes
if (!routes && method === 'head') {
routes = this.map.get;
}
}).map(function(method){
return method.toUpperCase();
});
if (!routes) continue;
for (var j = 0; j < routes.length; j++) {
if (routes[j].match(path)) {
options.push(method.toUpperCase());
break;
}
}
}
return options.sort();
};
/**

View File

@@ -1,7 +1,7 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "3.18.6",
"version": "3.19.2",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
@@ -27,22 +27,22 @@
],
"dependencies": {
"basic-auth": "1.0.0",
"connect": "2.27.6",
"connect": "2.28.3",
"content-disposition": "0.5.0",
"commander": "1.3.2",
"commander": "2.6.0",
"cookie-signature": "1.0.5",
"debug": "~2.1.0",
"debug": "~2.1.1",
"depd": "~1.0.0",
"escape-html": "1.0.1",
"etag": "~1.5.1",
"fresh": "0.2.4",
"media-typer": "0.3.0",
"methods": "1.1.0",
"methods": "~1.1.1",
"mkdirp": "0.5.0",
"parseurl": "~1.3.0",
"proxy-addr": "~1.0.4",
"proxy-addr": "~1.0.6",
"range-parser": "~1.0.2",
"send": "0.10.1",
"send": "0.11.1",
"utils-merge": "1.0.0",
"vary": "~1.0.0",
"cookie": "0.1.2",
@@ -50,13 +50,13 @@
},
"devDependencies": {
"connect-redis": "~1.5.0",
"ejs": "2.1.4",
"istanbul": "0.3.5",
"mocha": "~2.0.0",
"should": "~4.3.1",
"marked": "0.3.3",
"mocha": "~2.1.0",
"should": "~4.6.2",
"supertest": "~0.15.0",
"ejs": "~1.0.0",
"hjs": "~0.0.6",
"marked": "0.3.2"
"hjs": "~0.0.6"
},
"engines": {
"node": ">= 0.8.0"

View File

@@ -12,8 +12,8 @@ describe('OPTIONS', function(){
request(app)
.options('/users')
.expect('GET,PUT')
.expect('Allow', 'GET,PUT', done);
.expect('GET,HEAD,PUT')
.expect('Allow', 'GET,HEAD,PUT', done);
})
it('should not respond if the path is not defined', function(done){
@@ -36,8 +36,8 @@ describe('OPTIONS', function(){
request(app)
.options('/other')
.expect('GET')
.expect('Allow', 'GET', done);
.expect('GET,HEAD')
.expect('Allow', 'GET,HEAD', done);
})
})

View File

@@ -37,7 +37,7 @@ describe('req', function(){
var app = express();
app.use(function(req, res){
res._headers = undefined;
res._headers = null;
res.send(req.fresh);
});

View File

@@ -37,7 +37,7 @@ describe('req', function(){
var app = express();
app.use(function(req, res){
res._headers = undefined;
res._headers = null;
res.send(req.stale);
});

View File

@@ -81,7 +81,7 @@ describe('res', function(){
it('should be invoked instead of auto-responding', function(done){
request(app3)
.get('/')
.set('Accept: text/html')
.set('Accept', 'text/html')
.expect('default', done);
})
})

View File

@@ -1,14 +1,20 @@
var express = require('../')
, res = express.response;
var express = require('..');
var request = require('supertest');
describe('res', function(){
describe('.get(field)', function(){
it('should get the response header field', function(){
res.setHeader('Content-Type', 'text/x-foo');
res.get('Content-Type').should.equal('text/x-foo');
res.get('Content-type').should.equal('text/x-foo');
res.get('content-type').should.equal('text/x-foo');
it('should get the response header field', function (done) {
var app = express();
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/x-foo');
res.send(res.get('Content-Type'));
});
request(app)
.get('/')
.expect(200, 'text/x-foo', done);
})
})
})

View File

@@ -1,41 +1,46 @@
var express = require('../')
, res = express.response;
var express = require('..');
var request = require('supertest');
describe('res', function(){
beforeEach(function() {
res.removeHeader('link');
});
describe('.links(obj)', function(){
it('should set Link header field', function(){
res.links({
next: 'http://api.example.com/users?page=2',
last: 'http://api.example.com/users?page=5'
it('should set Link header field', function (done) {
var app = express();
app.use(function (req, res) {
res.links({
next: 'http://api.example.com/users?page=2',
last: 'http://api.example.com/users?page=5'
});
res.end();
});
res.get('link')
.should.equal(
'<http://api.example.com/users?page=2>; rel="next", '
+ '<http://api.example.com/users?page=5>; rel="last"');
request(app)
.get('/')
.expect('Link', '<http://api.example.com/users?page=2>; rel="next", <http://api.example.com/users?page=5>; rel="last"')
.expect(200, done);
})
it('should set Link header field for multiple calls', function() {
res.links({
next: 'http://api.example.com/users?page=2',
last: 'http://api.example.com/users?page=5'
it('should set Link header field for multiple calls', function (done) {
var app = express();
app.use(function (req, res) {
res.links({
next: 'http://api.example.com/users?page=2',
last: 'http://api.example.com/users?page=5'
});
res.links({
prev: 'http://api.example.com/users?page=1'
});
res.end();
});
res.links({
prev: 'http://api.example.com/users?page=1',
});
res.get('link')
.should.equal(
'<http://api.example.com/users?page=2>; rel="next", '
+ '<http://api.example.com/users?page=5>; rel="last", '
+ '<http://api.example.com/users?page=1>; rel="prev"');
request(app)
.get('/')
.expect('Link', '<http://api.example.com/users?page=2>; rel="next", <http://api.example.com/users?page=5>; rel="last", <http://api.example.com/users?page=1>; rel="prev"')
.expect(200, done);
})
})
})

View File

@@ -1,7 +1,6 @@
var express = require('../')
, request = require('supertest')
, res = express.response;
var express = require('..');
var request = require('supertest');
describe('res', function(){
describe('.set(field, value)', function(){
@@ -18,10 +17,18 @@ describe('res', function(){
.end(done);
})
it('should coerce to a string', function(){
res.headers = {};
res.set('X-Number', 123);
res.get('X-Number').should.equal('123');
it('should coerce to a string', function (done) {
var app = express();
app.use(function (req, res) {
res.set('X-Number', 123);
res.end(typeof res.get('X-Number'));
});
request(app)
.get('/')
.expect('X-Number', '123')
.expect(200, 'string', done);
})
})
@@ -39,11 +46,18 @@ describe('res', function(){
.expect('["type=ninja","language=javascript"]', done);
})
it('should coerce to an array of strings', function(){
res.headers = {};
res.set('X-Numbers', [123, 456]);
JSON.stringify(res.get('X-Numbers'))
.should.equal('["123","456"]');
it('should coerce to an array of strings', function (done) {
var app = express();
app.use(function (req, res) {
res.set('X-Numbers', [123, 456]);
res.end(JSON.stringify(res.get('X-Numbers')));
});
request(app)
.get('/')
.expect('X-Numbers', '123, 456')
.expect(200, '["123","456"]', done);
})
})
@@ -65,10 +79,18 @@ describe('res', function(){
.end(done);
})
it('should coerce to a string', function(){
res.headers = {};
res.set({ 'X-Number': 123 });
res.get('X-Number').should.equal('123');
it('should coerce to a string', function (done) {
var app = express();
app.use(function (req, res) {
res.set({ 'X-Number': 123 });
res.end(typeof res.get('X-Number'));
});
request(app)
.get('/')
.expect('X-Number', '123')
.expect(200, 'string', done);
})
})
})

View File

@@ -1,55 +1,96 @@
var express = require('../')
, should = require('should');
function response() {
var res = Object.create(express.response);
res._headers = {};
return res;
}
var assert = require('assert');
var express = require('..');
var request = require('supertest');
describe('res.vary()', function(){
describe('with no arguments', function(){
it('should not set Vary', function(){
var res = response();
res.vary();
should.not.exist(res.get('Vary'));
it('should not set Vary', function (done) {
var app = express();
app.use(function (req, res) {
res.vary();
res.end();
});
request(app)
.get('/')
.expect(shouldNotHaveHeader('Vary'))
.expect(200, done);
})
})
describe('with an empty array', function(){
it('should not set Vary', function(){
var res = response();
res.vary([]);
should.not.exist(res.get('Vary'));
it('should not set Vary', function (done) {
var app = express();
app.use(function (req, res) {
res.vary([]);
res.end();
});
request(app)
.get('/')
.expect(shouldNotHaveHeader('Vary'))
.expect(200, done);
})
})
describe('with an array', function(){
it('should set the values', function(){
var res = response();
res.vary(['Accept', 'Accept-Language', 'Accept-Encoding']);
res.get('Vary').should.equal('Accept, Accept-Language, Accept-Encoding');
it('should set the values', function (done) {
var app = express();
app.use(function (req, res) {
res.vary(['Accept', 'Accept-Language', 'Accept-Encoding']);
res.end();
});
request(app)
.get('/')
.expect('Vary', 'Accept, Accept-Language, Accept-Encoding')
.expect(200, done);
})
})
describe('with a string', function(){
it('should set the value', function(){
var res = response();
res.vary('Accept');
res.get('Vary').should.equal('Accept');
it('should set the value', function (done) {
var app = express();
app.use(function (req, res) {
res.vary('Accept');
res.end();
});
request(app)
.get('/')
.expect('Vary', 'Accept')
.expect(200, done);
})
})
describe('when the value is present', function(){
it('should not add it again', function(){
var res = response();
res.vary('Accept');
res.vary('Accept-Encoding');
res.vary('Accept-Encoding');
res.vary('Accept-Encoding');
res.vary('Accept');
res.get('Vary').should.equal('Accept, Accept-Encoding');
it('should not add it again', function (done) {
var app = express();
app.use(function (req, res) {
res.vary('Accept');
res.vary('Accept-Encoding');
res.vary('Accept-Encoding');
res.vary('Accept-Encoding');
res.vary('Accept');
res.end();
});
request(app)
.get('/')
.expect('Vary', 'Accept, Accept-Encoding')
.expect(200, done);
})
})
})
function shouldNotHaveHeader(header) {
return function (res) {
assert.ok(!(header.toLowerCase() in res.headers), 'should not have header ' + header);
};
}