Compare commits

...

15 Commits
3.4.7 ... 3.4.8

Author SHA1 Message Date
Jonathan Ong
ff23423d34 3.4.8 2014-01-13 20:50:51 -08:00
Doug Patti
1d97599f8b prevent incorrect automatic OPTIONS responses
The router has automatic handling of OPTIONS based on the registered
routes, but if you make an OPTIONS request for an endpoint that does
not exist, then it will still return a 200 with nothing allowed.
Instead, we can let the request move on down the middleware chain. This
has two benefits: first, if the route was not defined and no other
middleware handles it, it will return with a 404. Secondly, if multiple
routers are used and a later one has the route or a custom OPTIONS
defined, the first router will not respond incorrectly.
2014-01-13 20:46:07 -08:00
Matheus Azzi
e465624fd0 Update layout.jade 2014-01-13 20:45:50 -08:00
TJ Holowaychuk
dc5932d177 Merge pull request #1877 from reqshark/master
update express jade layout generator
2013-12-23 10:34:47 -08:00
Bent Cardan
cfd93b7529 update express jade layout generator
update doctype
2013-12-23 13:03:21 -05:00
Jonathan Ong
8b2208f394 Merge pull request #1876 from yosssi/dev
Updated the example file to use `doctype html` on  because  `doctype 5` was deprecated on Jade version 1.0.0.
2013-12-23 08:10:26 -08:00
yosssi
00a3b01f39 Changed doctype 5 to doctype html on the example file because the former was deprecated on Jade version 1.0.0. 2013-12-23 22:13:05 +09:00
TJ Holowaychuk
3baca251f0 use 8 threads for benchmarks 2013-12-22 08:57:04 -08:00
TJ Holowaychuk
72daae1d92 Merge pull request #1869 from yamatt/master
Error message now describes where the view was not able to be found.
2013-12-21 11:13:04 -08:00
Matt Copperwaite
fcbe53ddb5 Added appropriate test for more descriptive render error 2013-12-21 17:34:59 +00:00
Jonathan Ong
e9851672eb bench: remove --harmony-generators flag 2013-12-20 21:15:17 -08:00
TJ Holowaychuk
9a45f7bd3d add new benchmarks (to match koa) 2013-12-20 19:34:59 -08:00
Matt Copperwaite
85834fd146 Error message now describes where the view was not able to be found. Useful for debugging. 2013-12-20 11:39:31 +00:00
Roman Shtylman
a0c1ac7b45 add license field to package.json
close #1862
2013-12-18 10:16:56 -05:00
Alex Kocharin
7b0dca0f9c throw 400 in case of malformed paths 2013-12-11 17:14:44 -08:00
17 changed files with 165 additions and 84 deletions

View File

@@ -1,3 +1,25 @@
4.0.0 /
==================
* remove:
- express(1) - moved to [express-generator](https://github.com/expressjs/generator)
- `req.accepted*` - use `req.accepts*()` instead
- `app.configure` - use logic in your own app code
* change:
- `req.accepts*` -> `req.accepts*s` - i.e. `req.acceptsEncoding` -> `req.acceptsEncodings`
- `req.params` is now an object instead of an array
- `json spaces` no longer enabled by default in development
* refactor:
- `req.accepts*` with [accepts](https://github.com/expressjs/accepts)
- `req.is` with [type-is](https://github.com/expressjs/type-is)
3.4.8 / 2014-01-13
==================
* prevent incorrect automatic OPTIONS responses #1868 @dpatti
* update binary and examples for jade 1.0 #1876 @yossi, #1877 @reqshark, #1892 @matheusazzi
* throw 400 in case of malformed paths @rlidwka
3.4.7 / 2013-12-10
==================

View File

@@ -24,11 +24,11 @@ test-cov: lib-cov
lib-cov:
@jscoverage lib lib-cov
benchmark:
@./support/bench
bench:
@$(MAKE) -C benchmarks
clean:
rm -f coverage.html
rm -fr lib-cov
.PHONY: test test-unit test-acceptance benchmark clean
.PHONY: test test-unit test-acceptance bench clean

13
benchmarks/Makefile Normal file
View File

@@ -0,0 +1,13 @@
all:
@./run 1 middleware
@./run 5 middleware
@./run 10 middleware
@./run 15 middleware
@./run 20 middleware
@./run 30 middleware
@./run 50 middleware
@./run 100 middleware
@echo
.PHONY: all

23
benchmarks/middleware.js Normal file
View File

@@ -0,0 +1,23 @@
var http = require('http');
var express = require('..');
var app = express();
// number of middleware
var n = parseInt(process.env.MW || '1', 10);
console.log(' %s middleware', n);
while (n--) {
app.use(function(req, res, next){
next();
});
}
var body = new Buffer('Hello World');
app.use(function(req, res, next){
res.send(body);
});
app.listen(3333);

16
benchmarks/run Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
echo
MW=$1 node $2 &
pid=$!
sleep 2
wrk 'http://localhost:3333/?foo[bar]=baz' \
-d 3 \
-c 50 \
-t 8 \
| grep 'Requests/sec' \
| awk '{ print " " $2 }'
kill $pid

View File

@@ -74,7 +74,7 @@ var users = [
*/
var jadeLayout = [
'doctype 5'
'doctype html'
, 'html'
, ' head'
, ' title= title'

View File

@@ -1,5 +1,5 @@
!!! 5
doctype html
html
include header
body
block content
block content

View File

@@ -1,4 +1,4 @@
doctype 5
doctype html
html
head
title= title

View File

@@ -490,7 +490,7 @@ app.render = function(name, options, fn){
});
if (!view.path) {
var err = new Error('Failed to lookup view "' + name + '"');
var err = new Error('Failed to lookup view "' + name + '" in views directory "' + view.root + '"');
err.view = view;
return fn(err);
}

View File

@@ -104,7 +104,7 @@ Router.prototype._dispatch = function(req, res, next){
req.route = route = self.matchRequest(req, i);
// implied OPTIONS
if (!route && 'OPTIONS' == req.method) return self._options(req, res);
if (!route && 'OPTIONS' == req.method) return self._options(req, res, next);
// no route
if (!route) return next(err);
@@ -181,9 +181,10 @@ Router.prototype._dispatch = function(req, res, next){
* @api private
*/
Router.prototype._options = function(req, res){
Router.prototype._options = function(req, res, next){
var path = parse(req).pathname
, body = this._optionsFor(path).join(',');
if (!body) return next();
res.set('Allow', body).send(body);
};

View File

@@ -57,9 +57,15 @@ Route.prototype.match = function(path){
for (var i = 1, len = m.length; i < len; ++i) {
var key = keys[i - 1];
var val = 'string' == typeof m[i]
? utils.decode(m[i])
: m[i];
try {
var val = 'string' == typeof m[i]
? decodeURIComponent(m[i])
: m[i];
} catch(e) {
var err = new Error("Failed to decode param '" + m[i] + "'");
err.status = 400;
throw err;
}
if (key) {
params[key.name] = val;

View File

@@ -312,22 +312,3 @@ exports.pathRegexp = function(path, keys, sensitive, strict) {
.replace(/\*/g, '(.*)');
return new RegExp('^' + path + '$', sensitive ? '' : 'i');
}
/**
* Decodes a URI component. Returns
* the original string if the component
* is malformed.
*
* @param {String} str
* @return {String}
* @api private
*/
exports.decode = function(str) {
try {
return decodeURIComponent(str);
} catch (e) {
return str;
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "3.4.7",
"version": "3.4.8",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
{
@@ -68,5 +68,6 @@
},
"engines": {
"node": ">= 0.8.0"
}
},
"license": "MIT"
}

View File

@@ -1,32 +0,0 @@
#!/usr/bin/env bash
NODE_ENV=production node ./support/app &
pid=$!
bench() {
ab -n 5000 -c 50 -k -q http://127.0.0.1:8000$1 \
| grep "Requests per" \
| cut -d ' ' -f 7 \
| xargs echo "$2:"
}
bench_conditional() {
ab -n 5000 -c 50 -H "If-None-Match: $3" -k -q http://127.0.0.1:8000$1 \
| grep "Requests per" \
| cut -d ' ' -f 7 \
| xargs echo "$2:"
}
sleep .5
bench / "Hello World"
bench /blog "Mounted Hello World"
bench /blog/admin "Mounted 2 Hello World"
bench /middleware "Middleware"
bench /match "Router"
bench /render "Render"
bench /json "JSON tiny"
bench /json/15 "JSON small"
bench /json/50 "JSON medium"
bench /json/150 "JSON large"
kill -9 $pid

View File

@@ -15,6 +15,30 @@ describe('OPTIONS', function(){
.expect('GET,PUT')
.expect('Allow', 'GET,PUT', done);
})
it('should not respond if the path is not defined', function(done){
var app = express();
app.get('/users', function(req, res){});
request(app)
.options('/other')
.expect(404, done);
})
it('should forward requests down the middleware chain', function(done){
var app = express();
var router = new express.Router();
router.get('/users', function(req, res){});
app.use(router.middleware);
app.get('/other', function(req, res){});
request(app)
.options('/other')
.expect('GET')
.expect('Allow', 'GET', done);
})
})
describe('app.options()', function(){

View File

@@ -59,7 +59,7 @@ describe('app', function(){
var app = express();
app.set('views', __dirname + '/fixtures');
app.render('rawr.jade', function(err){
err.message.should.equal('Failed to lookup view "rawr.jade"');
err.message.should.equal('Failed to lookup view "rawr.jade" in views directory "' + __dirname + '/fixtures"');
done();
});
})

View File

@@ -27,28 +27,54 @@ describe('app.router', function(){
});
})
it('should decode params', function(done){
var app = express();
describe('decode querystring', function(){
it('should decode correct params', function(done){
var app = express();
app.get('/:name', function(req, res, next){
res.send(req.params.name);
});
app.get('/:name', function(req, res, next){
res.send(req.params.name);
});
request(app)
.get('/foo%2Fbar')
.expect('foo/bar', done);
})
request(app)
.get('/foo%2Fbar')
.expect('foo/bar', done);
})
it('should accept params in malformed paths', function(done) {
var app = express();
it('should not accept params in malformed paths', function(done) {
var app = express();
app.get('/:name', function(req, res, next){
res.send(req.params.name);
});
app.get('/:name', function(req, res, next){
res.send(req.params.name);
});
request(app)
.get('/%foobar')
.expect('%foobar', done);
request(app)
.get('/%foobar')
.expect(400, done);
})
it('should not decode spaces', function(done) {
var app = express();
app.get('/:name', function(req, res, next){
res.send(req.params.name);
});
request(app)
.get('/foo+bar')
.expect('foo+bar', done);
})
it('should work with unicode', function(done) {
var app = express();
app.get('/:name', function(req, res, next){
res.send(req.params.name);
});
request(app)
.get('/%ce%b1')
.expect('\u03b1', done);
})
})
it('should be .use()able', function(done){