Merge tag '3.6.0'

This commit is contained in:
Douglas Christopher Wilson 2014-05-09 17:33:26 -04:00
commit 35c50601bd
13 changed files with 242 additions and 18 deletions

View File

@ -1,9 +1,23 @@
4.2.x
=====
* deprecate `app.del()` -- use `app.delete()` instead
* deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead
- the edge-case `res.json(status, num)` requires `res.status(status).json(num)`
* deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead
- the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)`
* fix `req.next` when inside router instance
* include `ETag` header in `HEAD` requests
* keep previous `Content-Type` for `res.jsonp`
* support PURGE method
- add `app.purge`
- add `router.purge`
- include PURGE in `app.all`
* update debug to 0.8.0
- add `enable()` method
- change from stderr to stdout
* update methods to 1.0.0
- add PURGE
4.1.2 / 2014-05-08
==================
@ -80,6 +94,39 @@
- `app.route()` - Proxy to the app's `Router#route()` method to create a new route
- Router & Route - public API
3.6.0 / 2014-05-09
==================
* deprecate `app.del()` -- use `app.delete()` instead
* deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead
- the edge-case `res.json(status, num)` requires `res.status(status).json(num)`
* deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead
- the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)`
* support PURGE method
- add `app.purge`
- add `router.purge`
- include PURGE in `app.all`
* update connect to 2.15.0
* Add `res.appendHeader`
* Call error stack even when response has been sent
* Patch `res.headerSent` to return Boolean
* Patch `res.headersSent` for node.js 0.8
* Prevent default 404 handler after response sent
* dep: compression@1.0.2
* dep: connect-timeout@1.1.0
* dep: debug@^0.8.0
* dep: errorhandler@1.0.1
* dep: express-session@1.0.4
* dep: morgan@1.0.1
* dep: serve-favicon@2.0.0
* dep: serve-index@1.0.2
* update debug to 0.8.0
* add `enable()` method
* change from stderr to stdout
* update methods to 1.0.0
- add PURGE
* update mkdirp to 0.5.0
3.5.3 / 2014-05-08
==================

View File

@ -2,7 +2,7 @@
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
[![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express) [![Gittip](https://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/)
[![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express) [![Gittip](http://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/) [![NPM version](https://badge.fury.io/js/express.svg)](http://badge.fury.io/js/express)
```js
var express = require('express');

View File

@ -17,7 +17,7 @@ app.resource = function(path, obj) {
obj.range(req, res, a, b, format);
});
this.get(path + '/:id', obj.show);
this.del(path + '/:id', obj.destroy);
this.delete(path + '/:id', obj.destroy);
};
// Fake records

View File

@ -34,7 +34,7 @@ var users = {
res.send('user ' + req.params.uid);
},
del: function(req, res){
delete: function(req, res){
res.send('delete users');
}
};
@ -44,7 +44,7 @@ var pets = {
res.send('user ' + req.params.uid + '\'s pets');
},
del: function(req, res){
delete: function(req, res){
res.send('delete ' + req.params.uid + '\'s pet ' + req.params.pid);
}
};
@ -52,13 +52,13 @@ var pets = {
app.map({
'/users': {
get: users.list,
del: users.del,
delete: users.delete,
'/:uid': {
get: users.get,
'/pets': {
get: pets.list,
'/:pid': {
del: pets.del
delete: pets.delete
}
}
}

View File

@ -77,7 +77,7 @@ app.get('/user/:id/edit', loadUser, andRestrictToSelf, function(req, res){
res.send('Editing user ' + req.user.name);
});
app.del('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
app.delete('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
res.send('Deleted user ' + req.user.name);
});

View File

@ -11,6 +11,7 @@ var query = require('./middleware/query');
var debug = require('debug')('express:application');
var View = require('./view');
var http = require('http');
var deprecate = require('./utils').deprecate;
/**
* Application prototype.
@ -432,7 +433,7 @@ app.all = function(path){
// del -> delete alias
app.del = app.delete;
app.del = deprecate(app.delete, 'app.del: Use app.delete instead');
/**
* Render the given view `name` name with `options`

View File

@ -10,6 +10,7 @@ var sign = require('cookie-signature').sign;
var normalizeType = require('./utils').normalizeType;
var normalizeTypes = require('./utils').normalizeTypes;
var contentDisposition = require('./utils').contentDisposition;
var deprecate = require('./utils').deprecate;
var etag = require('./utils').etag;
var statusCodes = http.STATUS_CODES;
var cookie = require('cookie');
@ -174,6 +175,9 @@ res.json = function(obj){
// res.json(body, status) backwards compat
if ('number' == typeof arguments[1]) {
this.statusCode = arguments[1];
return 'number' === typeof obj
? jsonNumDeprecated.call(this, obj)
: jsonDeprecated.call(this, obj);
} else {
this.statusCode = obj;
obj = arguments[1];
@ -192,6 +196,12 @@ res.json = function(obj){
return this.send(body);
};
var jsonDeprecated = deprecate(res.json,
'res.json(obj, status): Use res.json(status, obj) instead');
var jsonNumDeprecated = deprecate(res.json,
'res.json(num, status): Use res.status(status).json(num) instead');
/**
* Send JSON response with JSONP callback support.
*
@ -214,6 +224,9 @@ res.jsonp = function(obj){
// res.json(body, status) backwards compat
if ('number' == typeof arguments[1]) {
this.statusCode = arguments[1];
return 'number' === typeof obj
? jsonpNumDeprecated.call(this, obj)
: jsonpDeprecated.call(this, obj);
} else {
this.statusCode = obj;
obj = arguments[1];
@ -247,6 +260,12 @@ res.jsonp = function(obj){
return this.send(body);
};
var jsonpDeprecated = deprecate(res.json,
'res.jsonp(obj, status): Use res.jsonp(status, obj) instead');
var jsonpNumDeprecated = deprecate(res.json,
'res.jsonp(num, status): Use res.status(status).jsonp(num) instead');
/**
* Transfer the file at the given `path`.
*

View File

@ -5,6 +5,22 @@
var mime = require('send').mime;
var crc32 = require('buffer-crc32');
var basename = require('path').basename;
var deprecate = require('util').deprecate;
/**
* Deprecate function, like core `util.deprecate`
*
* @param {Function} fn
* @param {String} msg
* @return {Function}
* @api private
*/
exports.deprecate = function(fn, msg){
return 'test' !== process.env.NODE_ENV
? deprecate(fn, 'express: ' + msg)
: fn;
};
/**
* Return ETag for `body`.

View File

@ -16,6 +16,10 @@
"name": "Ciaran Jessup",
"email": "ciaranj@gmail.com"
},
{
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
{
"name": "Guillermo Rauch",
"email": "rauchg@gmail.com"
@ -37,7 +41,7 @@
"cookie": "0.1.2",
"buffer-crc32": "0.2.1",
"fresh": "0.2.2",
"methods": "0.1.0",
"methods": "1.0.0",
"send": "0.3.0",
"cookie-signature": "1.0.3",
"merge-descriptors": "0.0.2",
@ -46,7 +50,7 @@
"qs": "0.6.6",
"serve-static": "1.1.0",
"path-to-regexp": "0.1.2",
"debug": ">= 0.7.3 < 1"
"debug": ">= 0.8.0 < 1"
},
"devDependencies": {
"mocha": "~1.18.2",
@ -58,7 +62,7 @@
"multiparty": "~3.2.4",
"hjs": "~0.0.6",
"should": "~3.3.1",
"supertest": "~0.11.0",
"supertest": "~0.12.0",
"method-override": "1.0.0",
"cookie-parser": "1.0.1",
"express-session": "1.0.4",

View File

@ -6,11 +6,10 @@ var express = require('../')
describe('app.router', function(){
describe('methods supported', function(){
methods.forEach(function(method){
methods.concat('del').forEach(function(method){
if (method === 'connect') return;
it('should include ' + method.toUpperCase(), function(done){
if (method == 'delete') method = 'del';
var app = express();
var calls = [];

View File

@ -4,9 +4,9 @@ var express = require('../')
, utils = require('../lib/utils')
, assert = require('assert');
var app = express();
var app1 = express();
app.use(function(req, res, next){
app1.use(function(req, res, next){
res.format({
'text/plain': function(){
res.send('hey');
@ -25,7 +25,7 @@ app.use(function(req, res, next){
});
});
app.use(function(err, req, res, next){
app1.use(function(err, req, res, next){
if (!err.types) throw err;
res.send(err.status, 'Supports: ' + err.types.join(', '));
})
@ -53,10 +53,24 @@ app3.use(function(req, res, next){
})
});
var app4 = express();
app4.get('/', function(req, res, next){
res.format({
text: function(){ res.send('hey') },
html: function(){ res.send('<p>hey</p>') },
json: function(){ res.send({ message: 'hey' }) }
});
});
app4.use(function(err, req, res, next){
res.send(err.status, 'Supports: ' + err.types.join(', '));
})
describe('res', function(){
describe('.format(obj)', function(){
describe('with canonicalized mime types', function(){
test(app);
test(app1);
})
describe('with extnames', function(){
@ -72,6 +86,10 @@ describe('res', function(){
})
})
describe('in router', function(){
test(app4);
})
describe('in router', function(){
var app = express();
var router = express.Router();

View File

@ -32,7 +32,7 @@ describe('res', function(){
})
describe('when given primitives', function(){
it('should respond with json', function(done){
it('should respond with json for null', function(done){
var app = express();
app.use(function(req, res){
@ -47,6 +47,40 @@ describe('res', function(){
done();
})
})
it('should respond with json for Number', function(done){
var app = express();
app.use(function(req, res){
res.json(300);
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(200);
res.headers.should.have.property('content-type', 'application/json');
res.text.should.equal('300');
done();
})
})
it('should respond with json for String', function(done){
var app = express();
app.use(function(req, res){
res.json('str');
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(200);
res.headers.should.have.property('content-type', 'application/json');
res.text.should.equal('"str"');
done();
})
})
})
describe('when given an array', function(){
@ -169,5 +203,22 @@ describe('res', function(){
done();
})
})
it('should use status as second number for backwards compat', function(done){
var app = express();
app.use(function(req, res){
res.json(200, 201);
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(201);
res.headers.should.have.property('content-type', 'application/json');
res.text.should.equal('200');
done();
})
})
})
})

View File

@ -201,6 +201,58 @@ describe('res', function(){
})
})
describe('when given primitives', function(){
it('should respond with json for null', function(done){
var app = express();
app.use(function(req, res){
res.jsonp(null);
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'application/json');
res.text.should.equal('null');
done();
})
})
it('should respond with json for Number', function(done){
var app = express();
app.use(function(req, res){
res.jsonp(300);
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(200);
res.headers.should.have.property('content-type', 'application/json');
res.text.should.equal('300');
done();
})
})
it('should respond with json for String', function(done){
var app = express();
app.use(function(req, res){
res.jsonp('str');
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(200);
res.headers.should.have.property('content-type', 'application/json');
res.text.should.equal('"str"');
done();
})
})
})
describe('"json replacer" setting', function(){
it('should be passed to JSON.stringify()', function(done){
var app = express();
@ -285,5 +337,22 @@ describe('res', function(){
done();
})
})
it('should use status as second number for backwards compat', function(done){
var app = express();
app.use(function(req, res){
res.jsonp(200, 201);
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(201);
res.headers.should.have.property('content-type', 'application/json');
res.text.should.equal('200');
done();
})
})
})
})