Compare commits

...

11 Commits
2.3.2 ... 2.3.3

Author SHA1 Message Date
Tj Holowaychuk
8afb905a43 Release 2.3.3 2011-05-03 11:31:16 -07:00
Tj Holowaychuk
53667728a8 Fixed route-specific middleware when using the same callback function several times 2011-05-03 11:28:33 -07:00
Tj Holowaychuk
5f0a854e29 added test for route specific middleware regression 2011-05-03 11:25:54 -07:00
Tj Holowaychuk
e9ef3dd9cd ws 2011-05-03 09:41:59 -07:00
Tj Holowaychuk
f702884704 split methods supported by rfc [slaskis] 2011-05-03 09:24:51 -07:00
Tj Holowaychuk
0cb866845d npm 1.x docs 2011-05-02 12:48:45 -07:00
Tj Holowaychuk
26483029db docs for next("route"). Closes #650 2011-05-01 11:06:37 -07:00
Tj Holowaychuk
d2adcbdf67 Added "case sensitive routes" option. 2011-04-29 16:41:20 -07:00
Tj Holowaychuk
d2f963db2a fixed tests 2011-04-29 16:34:22 -07:00
TJ Holowaychuk
fc2bc1362f Merged pull request #645 from 8bitDesigner/patch-1.
Incorrect reference to template in a comment
2011-04-27 18:56:00 -07:00
8bitDesigner
6ae45d0fd3 The comment here refers to using "jade" for layouts, but you're using "ejs" instead. 2011-04-27 16:11:39 -07:00
14 changed files with 145 additions and 38 deletions

View File

@@ -1,4 +1,11 @@
2.3.3 / 2011-05-03
==================
* Added "case sensitive routes" option.
* Changed; split methods supported per rfc [slaskis]
* Fixed route-specific middleware when using the same callback function several times
2.3.2 / 2011-04-27
==================

View File

@@ -16,6 +16,10 @@
$ npm install express
or to access the `express(1)` executable install globally:
$ npm install -g express
## Features
* Robust routing

View File

@@ -11,7 +11,7 @@ var fs = require('fs')
* Framework version.
*/
var version = '2.3.2';
var version = '2.3.3';
/**
* Add session support.

View File

@@ -83,6 +83,7 @@ Express supports the following settings out of the box:
* _view engine_ Default view engine name for views rendered without extensions
* _view options_ An object specifying global view options
* _view cache_ Enable view caching (enabled in production)
* _case sensitive routes_ Enable case-sensitive routing
### Routing
@@ -319,6 +320,8 @@ Commonly used "stacks" of middleware can be passed as an array (_applied recursi
For this example in full, view the [route middleware example](http://github.com/visionmedia/express/blob/master/examples/route-middleware/app.js) in the repository.
There are times when we may want to "skip" passed remaining route middleware, but continue matching subsequent routes. To do this we invoke `next()` with the string "route" `next('route')`. If no remaining routes match the request url then Express will respond with 404 Not Found.
### HTTP Methods
We have seen _app.get()_ a few times, however Express also exposes other familiar HTTP verbs in the same manor, such as _app.post()_, _app.del()_, etc.

View File

@@ -1,4 +1,3 @@
// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');
@@ -15,7 +14,7 @@ app.set('views', __dirname + '/views');
// set default layout, usually "layout"
app.set('view options', { layout: 'layouts/default' });
// Set our default template engine to "jade"
// Set our default template engine to "ejs"
// which prevents the need for extensions
// (although you can still mix and match)
app.set('view engine', 'ejs');

View File

@@ -28,7 +28,7 @@ var exports = module.exports = connect.middleware;
* Framework version.
*/
exports.version = '2.3.2';
exports.version = '2.3.3';
/**
* Shortcut for `new Server(...)`.

View File

@@ -87,7 +87,7 @@ app.init = function(middleware){
if (middleware) middleware.forEach(self.use.bind(self));
// use router, expose as app.get(), etc
var fn = router(function(app){ self.routes = app; });
var fn = router(function(app){ self.routes = app; }, this);
this.__defineGetter__('router', function(){
this.__usedRouter = true;
return fn;

View File

@@ -34,7 +34,7 @@ exports.methods = _methods;
* @api private
*/
function router(fn){
function router(fn, app){
var self = this
, methods = {}
, routes = {}
@@ -79,12 +79,12 @@ function router(fn){
middleware = utils.flatten(middleware);
}
fn.middleware = middleware;
if (!path) throw new Error(name + ' route requires a path');
if (!fn) throw new Error(name + ' route ' + path + ' requires a callback');
var route = new Route(name, path, fn);
var options = { sensitive: app.enabled('case sensitive routes') };
var route = new Route(name, path, fn, options);
route.middleware = middleware;
localRoutes.push(route);
return self;
};
@@ -128,7 +128,7 @@ function router(fn){
// route middleware
i = 0;
(function nextMiddleware(err){
var fn = route.callback.middleware[i++];
var fn = route.middleware[i++];
if ('route' == err) {
pass(req._route_index + 1);
} else if (err) {

View File

@@ -6,26 +6,65 @@
*/
/**
* Supported HTTP / WebDAV methods.
* Hypertext Transfer Protocol -- HTTP/1.1
* http://www.ietf.org/rfc/rfc2616.txt
*/
module.exports = [
'get'
, 'post'
, 'put'
, 'delete'
, 'connect'
, 'options'
, 'trace'
, 'copy'
, 'lock'
, 'mkcol'
, 'move'
, 'propfind'
, 'proppatch'
, 'unlock'
, 'report'
, 'mkactivity'
, 'checkout'
, 'merge'
];
var RFC2616 = ['OPTIONS', 'GET', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT'];
/**
* HTTP Extensions for Distributed Authoring -- WEBDAV
* http://www.ietf.org/rfc/rfc2518.txt
*/
var RFC2518 = ['PROPFIND', 'PROPPATCH', 'MKCOL', 'COPY', 'MOVE', 'LOCK', 'UNLOCK'];
/**
* Versioning Extensions to WebDAV
* http://www.ietf.org/rfc/rfc3253.txt
*/
var RFC3253 = ['VERSION-CONTROL', 'REPORT', 'CHECKOUT', 'CHECKIN', 'UNCHECKOUT', 'MKWORKSPACE', 'UPDATE', 'LABEL', 'MERGE', 'BASELINE-CONTROL', 'MKACTIVITY'];
/**
* Ordered Collections Protocol (WebDAV)
* http://www.ietf.org/rfc/rfc3648.txt
*/
var RFC3648 = ['ORDERPATCH'];
/**
* Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol
* http://www.ietf.org/rfc/rfc3744.txt
*/
var RFC3744 = ['ACL'];
/**
* Web Distributed Authoring and Versioning (WebDAV) SEARCH
* http://www.ietf.org/rfc/rfc5323.txt
*/
var RFC5323 = ['SEARCH'];
/**
* PATCH Method for HTTP
* http://www.ietf.org/rfc/rfc5789.txt
*/
var RFC5789 = ['PATCH'];
/**
* Expose the methods.
*/
module.exports = [].concat(
RFC2616
, RFC2518
, RFC3253
, RFC3648
, RFC3744
, RFC5323
, RFC5789).map(function(method){
return method.toLowerCase();
});

View File

@@ -13,18 +13,24 @@ module.exports = Route;
/**
* Initialize `Route` with the given HTTP `method`, `path`,
* and callback `fn`.
* and callback `fn` and `options`.
*
* Options:
*
* - `sensitive` enable case-sensitive routes
*
* @param {String} method
* @param {String} path
* @param {Function} fn
* @param {Object} options.
* @api private
*/
function Route(method, path, fn) {
function Route(method, path, fn, options) {
options = options || {};
this.callback = fn;
this.path = path;
this.regexp = normalize(path, this.keys = []);
this.regexp = normalize(path, this.keys = [], options.sensitive);
this.method = method;
}
@@ -39,11 +45,12 @@ function Route(method, path, fn) {
*
* @param {String|RegExp} path
* @param {Array} keys
* @param {Boolean} sensitive
* @return {RegExp}
* @api private
*/
function normalize(path, keys) {
function normalize(path, keys, sensitive) {
if (path instanceof RegExp) return path;
path = path
.concat('/?')
@@ -60,5 +67,5 @@ function normalize(path, keys) {
})
.replace(/([\/.])/g, '\\$1')
.replace(/\*/g, '(.+)');
return new RegExp('^' + path + '$', 'i');
return new RegExp('^' + path + '$', sensitive ? '' : 'i');
}

View File

@@ -49,7 +49,7 @@ function View(view, options) {
this.name = this.basename.replace(this.extension, '');
this.path = this.resolvePath();
this.dirname = dirname(this.path);
options.attempts.push(this.path);
if (options.attempts) options.attempts.push(this.path);
};
/**

View File

@@ -1,7 +1,7 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "2.3.2",
"version": "2.3.3",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
{ "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },

View File

@@ -435,5 +435,31 @@ module.exports = {
{ url: '/' },
{ body: 'restored' }
);
},
'test routes with same callback': function(){
function handle(req, res) {
res.send('got ' + req.string);
}
var app = express.createServer();
app.get('/', function(req, res, next){
req.string = '/';
next();
}, handle);
app.get('/another', function(req, res, next){
req.string = '/another';
next();
}, handle);
assert.response(app,
{ url: '/' },
{ body: 'got /' });
assert.response(app,
{ url: '/another' },
{ body: 'got /another' });
}
};

View File

@@ -241,5 +241,27 @@ module.exports = {
app.match.get('/').should.have.be.empty;
app.match.all('/user/123').should.have.length(3);
app.match('/user/123').should.have.length(3);
},
'test "case sensitive routes" setting': function(){
var app = express.createServer();
app.enable('case sensitive routes');
app.get('/account', function(req, res){
res.send('account');
});
app.get('/Account', function(req, res){
res.send('Account');
});
assert.response(app,
{ url: '/account' },
{ body: 'account' });
assert.response(app,
{ url: '/Account' },
{ body: 'Account' });
}
};