Comparar commits

...

24 Commits

Autor SHA1 Mensagem Data
Tj Holowaychuk d9aa7c3bc9 Release 2.3.4 2011-05-08 10:53:57 -07:00
Tj Holowaychuk 986fac583b Merge branch 'master' of github.com:visionmedia/express 2011-05-08 10:52:59 -07:00
Tj Holowaychuk c6d76086e2 Fixed res.sendfile() bug preventing the transfer of files with spaces
params are decoded so we need to encode before passing to send() which then
in turn decodes it again, however nodes url module chokes on the spaces.
2011-05-08 10:52:16 -07:00
Tj Holowaychuk e2771364eb Updated connect submodule 2011-05-08 10:45:42 -07:00
Tj Holowaychuk 0d5a63798b added failing test with spaces in filename 2011-05-08 10:40:37 -07:00
TJ Holowaychuk 7d15e2bf52 Merge pull request #653 from darrentorpey/patch-1.
Fixed a typo: "A route is simple a string" => "A route is simply a string
2011-05-04 09:35:49 -07:00
Darren Torpey 31fef407b6 Fixed a typo: "A route is simple a string" => "A route is simply a string" 2011-05-04 04:14:40 -07:00
Tj Holowaychuk 6bef3ef891 misc 2011-05-03 16:48:17 -07:00
Tj Holowaychuk b806846049 misc 2011-05-03 16:44:17 -07:00
Tj Holowaychuk bc16020976 added stupid say example 2011-05-03 16:40:20 -07:00
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
Tj Holowaychuk cc185a8c0e Release 2.3.2 2011-04-27 09:12:54 -07:00
Tj Holowaychuk ae1078944c Fixed view hints
populate attempts on new View
2011-04-27 09:07:56 -07:00
Tj Holowaychuk 385a05dd10 bump 2011-04-26 15:26:24 -07:00
21 arquivos alterados com 217 adições e 45 exclusões
+18
Ver Arquivo
@@ -1,4 +1,22 @@
2.3.4 / 2011-05-08
==================
* Added `./examples/say`
* Fixed `res.sendfile()` bug preventing the transfer of files with spaces
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
==================
* Fixed view hints
2.3.1 / 2011-04-26
==================
+4
Ver Arquivo
@@ -16,6 +16,10 @@
$ npm install express
or to access the `express(1)` executable install globally:
$ npm install -g express
## Features
* Robust routing
+1 -1
Ver Arquivo
@@ -11,7 +11,7 @@ var fs = require('fs')
* Framework version.
*/
var version = '2.3.0';
var version = '2.3.4';
/**
* Add session support.
+1 -1
Ver Arquivo
@@ -355,7 +355,7 @@ are available as <code>req.params</code>.</p>
});
</code></pre>
<p>A route is simple a string which is compiled to a <em>RegExp</em> internally. For example
<p>A route is simply a string which is compiled to a <em>RegExp</em> internally. For example
when <em>/user/:id</em> is compiled, a simplified version of the regexp may look similar to:</p>
<pre><code>\/user\/([^\/]+)\/?
+3
Ver Arquivo
@@ -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.
+1 -2
Ver Arquivo
@@ -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');
+47
Ver Arquivo
@@ -0,0 +1,47 @@
// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');
/**
* Module dependencies.
*/
var express = require('../../')
, path = require('path')
, exec = require('child_process').exec
, fs = require('fs');
/**
* Error handler.
*/
function errorHandler(voice) {
return function(err, req, res, next) {
var parts = err.stack.split('\n')[1].split(/[()]/)[1].split(':')
, filename = parts.shift()
, basename = path.basename(filename)
, lineno = parts.shift()
, col = parts.shift()
, lines = fs.readFileSync(filename, 'utf8').split('\n')
, line = lines[lineno - 1].replace(/\./, ' ');
exec('say -v "' + voice + '" '
+ err.message
+ ' on line ' + lineno
+ ' of ' + basename + '.'
+ ' The contents of this line is '
+ ' "' + line + '".');
res.send(500);
}
}
var app = express.createServer();
app.get('/', function(request, response){
if (request.is(foo)) response.end('bar');
});
app.use(errorHandler('Vicki'));
app.listen(3000);
+1 -1
Ver Arquivo
@@ -28,7 +28,7 @@ var exports = module.exports = connect.middleware;
* Framework version.
*/
exports.version = '2.3.1';
exports.version = '2.3.4';
/**
* Shortcut for `new Server(...)`.
+1 -1
Ver Arquivo
@@ -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;
+1 -1
Ver Arquivo
@@ -141,7 +141,7 @@ res.sendfile = function(path, options, fn){
options = {};
}
options.path = path;
options.path = encodeURIComponent(path);
options.callback = fn;
send(this.req, this, next, options);
};
+5 -5
Ver Arquivo
@@ -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) {
+60 -21
Ver Arquivo
@@ -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();
});
+12 -5
Ver Arquivo
@@ -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');
}
+6 -5
Ver Arquivo
@@ -277,6 +277,9 @@ res._render = function(view, opts, fn, parent, sub){
// status support
if (options.status) this.statusCode = options.status;
// capture attempts
options.attempts = [];
var partial = options.renderPartial
, layout = options.layout;
@@ -403,10 +406,8 @@ res._render = function(view, opts, fn, parent, sub){
function hintAtViewPaths(view, options) {
console.error();
console.error('failed to locate view "' + view.view + '", tried:');
console.error(' - ' + new View(view.path, options).path);
console.error(' - ' + new View(view.prefixPath, options).path);
console.error(' - ' + new View(view.indexPath, options).path);
if (!options.isLayout) console.error(' - ' + new View(view.upIndexPath, options).path);
if (options.isLayout) console.error(' - ' + new View(view.rootPath, options).path);
options.attempts.forEach(function(path){
console.error(' - %s', path);
});
console.error();
}
+1
Ver Arquivo
@@ -49,6 +49,7 @@ function View(view, options) {
this.name = this.basename.replace(this.extension, '');
this.path = this.resolvePath();
this.dirname = dirname(this.path);
if (options.attempts) options.attempts.push(this.path);
};
/**
+1 -1
Ver Arquivo
@@ -1,7 +1,7 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "2.3.1",
"version": "2.3.4",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
{ "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },
+26
Ver Arquivo
@@ -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' });
}
};
+1
Ver Arquivo
@@ -0,0 +1 @@
hello
+4
Ver Arquivo
@@ -544,6 +544,10 @@ module.exports = {
assert.equal(null, res.headers['content-disposition']);
});
assert.response(app,
{ url: '/some%20random%20text%20file.txt' },
{ body: 'hello' });
beforeExit(function(){
calls.should.equal(1);
});
+22
Ver Arquivo
@@ -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' });
}
};