Comparar commits

...

20 Commits

Autor SHA1 Mensagem Data
Tj Holowaychuk 658e064220 Release 2.3.0 2011-04-25 09:49:54 -07:00
Tj Holowaychuk 66b472e567 connect >= 1.4.0 2011-04-25 09:32:57 -07:00
Tj Holowaychuk 3d242a607e Fixed caching of views when using several apps. Closes #637
simple fix :)
2011-04-25 09:25:23 -07:00
Tj Holowaychuk bc68e5e7a3 misc 2011-04-25 09:20:31 -07:00
Tj Holowaychuk aa6858189c misc refactor 2011-04-23 18:54:49 -07:00
Tj Holowaychuk 06fda62c9e Merge branch 'refactor/route-middleware' 2011-04-22 16:49:04 -07:00
Tj Holowaychuk 5688ea650d Fixed gotcha invoking app.param() callbacks once per route middleware. Closes #638 2011-04-22 16:48:54 -07:00
Tj Holowaychuk f5c4e9d612 Updated connect submodule 2011-04-22 16:34:42 -07:00
Tj Holowaychuk b9eda2a59d Updated connect submodule 2011-04-22 16:11:13 -07:00
Tj Holowaychuk 8c168b0971 connect >= 1.3.1 < 2.0.0 2011-04-22 16:11:07 -07:00
Tj Holowaychuk 9c20a50ee2 Added failing test for gotcha 2011-04-22 14:44:08 -07:00
Tj Holowaychuk eac666574e viewHelpers -> _locals 2011-04-21 08:26:30 -07:00
Tj Holowaychuk e4c840f6b8 Added res.helpers() as alias of res.locals()
to match app.locals() / app.helpers()
2011-04-20 15:26:22 -07:00
Daniel Shaw 3afbcd0acf JSON and JSONP default to UTF-8 in the same way as HTML. Closes #632.
Signed-off-by: Tj Holowaychuk <tj@vision-media.ca>
2011-04-20 09:00:02 -07:00
Daniel Shaw 8f054dbcaf JSON and JSONP default to UTF-8 in the same way as HTML. Introduces app.set('charset') to set charset default at the application level. Closes #632.
Signed-off-by: Tj Holowaychuk <tj@vision-media.ca>
2011-04-20 09:00:02 -07:00
Tj Holowaychuk ccc39e5aa2 Fixed partial lookup precedence. Closes #631 2011-04-19 10:23:16 -07:00
Tj Holowaychuk 53d4da2a9c Added failing partial precedence test 2011-04-19 10:19:45 -07:00
Tj Holowaychuk d9e7153fc9 Renamed "cache views" to "view cache". Closes #628 2011-04-17 16:42:03 -07:00
Tj Holowaychuk dc02b0d5ae Added options support to res.clearCookie() 2011-04-17 16:37:16 -07:00
Aaron Heckmann e0bc5711b8 auto set Content-Type in res.attachement
Signed-off-by: Tj Holowaychuk <tj@vision-media.ca>
2011-04-14 13:48:22 -07:00
14 arquivos alterados com 88 adições e 60 exclusões
+15
Ver Arquivo
@@ -1,4 +1,19 @@
2.3.0 / 2011-04-25
==================
* Added options support to `res.clearCookie()`
* Added `res.helpers()` as alias of `res.locals()`
* Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0`
* Changed; auto set Content-Type in res.attachement [Aaron Heckmann]
* Renamed "cache views" to "view cache". Closes #628
* Fixed caching of views when using several apps. Closes #637
* Fixed gotcha invoking `app.param()` callbacks once per route middleware.
Closes #638
* Fixed partial lookup precedence. Closes #631
Shaw]
2.2.2 / 2011-04-12
==================
+1 -1
Ver Arquivo
@@ -11,7 +11,7 @@ var fs = require('fs')
* Framework version.
*/
var version = '2.2.2';
var version = '2.3.0';
/**
* Add session support.
+1 -1
Ver Arquivo
@@ -894,7 +894,7 @@ To parse incoming _Cookie_ headers, use the _cookieParser_ middleware, which pro
// use req.cookies.rememberme
});
### res.clearCookie(name)
### res.clearCookie(name[, options])
Clear cookie _name_ by setting "expires" far in the past.
+1 -1
Ver Arquivo
@@ -27,7 +27,7 @@ var exports = module.exports = connect.middleware;
* Framework version.
*/
exports.version = '2.2.2';
exports.version = '2.3.0';
/**
* Shortcut for `new Server(...)`.
+7 -23
Ver Arquivo
@@ -44,12 +44,13 @@ Server.prototype.__proto__ = connect.HTTPServer.prototype;
Server.prototype.init = function(middleware){
var self = this;
this.cache = {};
this.match = {};
this.lookup = {};
this.settings = {};
this.redirects = {};
this.isCallbacks = {};
this.viewHelpers = {};
this._locals = {};
this.dynamicViewHelpers = {};
this.errorHandlers = [];
@@ -98,7 +99,7 @@ Server.prototype.init = function(middleware){
// default production configuration
this.configure('production', function(){
this.enable('cache views');
this.enable('view cache');
});
// register error handlers on "listening"
@@ -241,7 +242,7 @@ Server.prototype.register = function(){
Server.prototype.helpers =
Server.prototype.locals = function(obj){
utils.merge(this.viewHelpers, obj);
utils.merge(this._locals, obj);
return this;
};
@@ -450,7 +451,7 @@ Server.prototype.configure = function(env, fn){
// Generate routing methods
function generateMethod(method){
Server.prototype[method] = function(path, fn){
Server.prototype[method] = function(path){
var self = this;
// Lookup
@@ -461,27 +462,10 @@ function generateMethod(method){
}
// Ensure router is mounted
if (!this.__usedRouter) {
this.use(this.router);
}
// Route specific middleware support
if (arguments.length > 2) {
var args = Array.prototype.slice.call(arguments, 1);
fn = args.pop();
(function stack(middleware){
middleware.forEach(function(fn){
if (Array.isArray(fn)) {
stack(fn);
} else {
self[method](path, fn);
}
});
})(args);
}
if (!this.__usedRouter) this.use(this.router);
// Generate the route
this.routes[method](path, fn);
this.routes[method].apply(this, arguments);
return this;
};
return arguments.callee;
+12 -4
Ver Arquivo
@@ -75,10 +75,12 @@ res.send = function(body, headers, status){
}
} else {
if (!this.header('Content-Type')) {
this.charset = this.charset || 'utf-8';
this.contentType('.json');
}
body = JSON.stringify(body);
if (this.req.query.callback && this.app.set('jsonp callback')) {
this.charset = this.charset || 'utf-8';
this.header('Content-Type', 'text/javascript');
body = this.req.query.callback.replace(/[^\w$.]/g, '') + '(' + body + ');';
}
@@ -176,6 +178,7 @@ res.contentType = function(type){
*/
res.attachment = function(filename){
if (filename) this.contentType(filename);
this.header('Content-Disposition', filename
? 'attachment; filename="' + path.basename(filename) + '"'
: 'attachment');
@@ -211,7 +214,7 @@ res.download = function(path, filename, fn, fn2){
if (err) {
if (!sentHeader) self.removeHeader('Content-Disposition');
if (sentHeader) {
if (fn2) fn2(err);
fn2 && fn2(err);
} else if (fn) {
fn(err);
} else {
@@ -245,11 +248,15 @@ res.header = function(name, val){
* Clear cookie `name`.
*
* @param {String} name
* @param {Object} options
* @api public
*/
res.clearCookie = function(name){
this.cookie(name, '', { expires: new Date(1) });
res.clearCookie = function(name, options){
var opts = { expires: new Date(1) };
this.cookie(name, '', options
? utils.merge(options, opts)
: opts);
};
/**
@@ -404,7 +411,8 @@ res.local = function(name, val){
* @api public
*/
res.locals = function(obj){
res.locals =
res.helpers = function(obj){
if (obj) {
for (var key in obj) {
this.local(key, obj[key]);
+9 -14
Ver Arquivo
@@ -21,14 +21,6 @@ var path = require('path')
, http = require('http')
, res = http.ServerResponse.prototype;
/**
* Memory cache.
*
* @type Object
*/
var cache = {};
/**
* Expose constructors.
*/
@@ -261,10 +253,10 @@ res._render = function(view, opts, fn, parent, sub){
var options = {}
, self = this
, app = this.app
, helpers = app.viewHelpers
, helpers = app._locals
, dynamicHelpers = app.dynamicViewHelpers
, viewOptions = app.set('view options')
, cacheViews = app.set('cache views')
, cacheViews = app.enabled('view cache')
, root = app.set('views') || process.cwd() + '/views';
// merge "view options"
@@ -331,15 +323,18 @@ res._render = function(view, opts, fn, parent, sub){
};
// cached view
if (cache[view]) {
view = cache[view];
if (app.cache[view]) {
view = app.cache[view];
options.filename = view.path;
// resolve view
} else {
var orig = view = new View(view, options);
// Try _ prefix ex: ./views/_<name>.jade
if (!view.exists) view = new View(orig.prefixPath, options);
if (partial) {
view = new View(orig.prefixPath, options);
if (!view.exists) view = orig;
}
// Try index ex: ./views/user/index.jade
if (!view.exists) view = new View(orig.indexPath, options);
@@ -365,7 +360,7 @@ res._render = function(view, opts, fn, parent, sub){
options.filename = view.path;
var engine = view.templateEngine;
view.fn = engine.compile(view.contents, options)
if (cacheViews) cache[orig.view] = view;
if (cacheViews) app.cache[orig.view] = view;
}
// layout helper
+2 -2
Ver Arquivo
@@ -1,7 +1,7 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "2.2.2",
"version": "2.3.0",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
{ "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },
@@ -10,7 +10,7 @@
{ "name": "Guillermo Rauch", "email": "rauchg@gmail.com" }
],
"dependencies": {
"connect": ">= 1.3.0 < 2.0.0",
"connect": ">= 1.4.0 < 2.0.0",
"mime": ">= 0.0.1",
"qs": ">= 0.0.6"
},
+17 -3
Ver Arquivo
@@ -435,8 +435,9 @@ module.exports = {
);
},
'test route middleware': function(){
var app = express.createServer();
'test route middleware': function(beforeExit){
var app = express.createServer()
, calls = 0;
function allow(role) {
return function(req, res, next) {
@@ -460,6 +461,11 @@ module.exports = {
}
}
app.param('user', function(req, res, next, user){
++calls;
next();
});
app.get('/xxx', allow('member'), restrictAge(18), function(req, res){
res.send(200);
});
@@ -471,8 +477,12 @@ module.exports = {
app.get('/tobi', [allow('member')], [[restrictAge(18)]], function(req, res){
res.send(200);
});
app.get('/user/:user', [allow('member')], [[restrictAge(18)]], function(req, res){
res.send(200);
});
['xxx', 'booze', 'tobi'].forEach(function(thing){
['xxx', 'booze', 'tobi', 'user/tj'].forEach(function(thing){
assert.response(app,
{ url: '/' + thing },
{ body: 'Unauthorized', status: 401 });
@@ -483,6 +493,10 @@ module.exports = {
{ url: '/' + thing, headers: { 'X-Role': 'member', 'X-Age': 18 }},
{ body: 'OK', status: 200 });
});
beforeExit(function(){
calls.should.equal(3);
});
},
'test named capture groups': function(){
+1
Ver Arquivo
@@ -0,0 +1 @@
p two
+1
Ver Arquivo
@@ -0,0 +1 @@
p one
+12 -10
Ver Arquivo
@@ -61,7 +61,7 @@ module.exports = {
assert.response(app,
{ url: '/bool' },
{ body: 'true'
, headers: { 'Content-Type': 'application/json' }});
, headers: { 'Content-Type': 'application/json; charset=utf-8' }});
assert.response(app,
{ url: '/html' },
@@ -76,7 +76,7 @@ module.exports = {
{ body: '{"foo":"bar"}'
, status: 201
, headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json; charset=utf-8'
, 'X-Foo': 'baz'
}});
@@ -85,7 +85,7 @@ module.exports = {
{ body: 'test({"foo":"bar"});'
, status: 201
, headers: {
'Content-Type': 'text/javascript'
'Content-Type': 'text/javascript; charset=utf-8'
, 'X-Foo': 'baz'
}});
@@ -93,7 +93,7 @@ module.exports = {
{ url: '/jsonp?callback=baz' },
{ body: 'baz({"foo":"bar"});'
, status: 201, headers: {
'Content-Type': 'text/javascript'
'Content-Type': 'text/javascript; charset=utf-8'
, 'X-Foo': 'baz'
}});
@@ -102,7 +102,7 @@ module.exports = {
{ body: 'invalid({"foo":"bar"});'
, status: 201
, headers: {
'Content-Type': 'text/javascript'
'Content-Type': 'text/javascript; charset=utf-8'
, 'X-Foo': 'baz'
}});
@@ -111,7 +111,7 @@ module.exports = {
{ body: '{"foo":"bar"}'
, status: 201
, headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json; charset=utf-8'
, 'X-Foo': 'baz'
}});
@@ -207,12 +207,14 @@ module.exports = {
assert.response(app,
{ url: '/javascripts/jquery.js' },
{ body: 'whatever'
, headers: { 'Content-Disposition': 'attachment; filename="jquery.js"' }});
, headers: { 'Content-Type': 'application/javascript'
, 'Content-Disposition': 'attachment; filename="jquery.js"' }});
assert.response(app,
{ url: '/style.css' },
{ body: 'some stylezzz'
, headers: { 'Content-Disposition': 'attachment' }});
, headers: { 'Content-Type': 'text/html; charset=utf-8'
, 'Content-Disposition': 'attachment' }});
},
'test #redirect()': function(){
@@ -568,7 +570,7 @@ module.exports = {
var app = express.createServer();
app.get('/', function(req, res){
res.clearCookie('rememberme');
res.clearCookie('rememberme', { path: '/foo' });
res.redirect('/');
});
@@ -576,7 +578,7 @@ module.exports = {
{ url: '/' },
function(res){
res.headers['set-cookie']
.should.eql(['rememberme=; expires=Thu, 01 Jan 1970 00:00:00 GMT']);
.should.eql(['rememberme=; path=/foo; expires=Thu, 01 Jan 1970 00:00:00 GMT']);
});
},
+8
Ver Arquivo
@@ -657,6 +657,14 @@ module.exports = {
assert.response(app,
{ url: '/error' },
{ status: 500 });
app.get('/underscore', function(req, res, next){
res.partial('foobar');
});
assert.response(app,
{ url: '/underscore' },
{ body: '<p>two</p>' });
},
'test #partial() with several calls': function(){