Comparar commits
81 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 72b9e48331 | |||
| eba6aa1767 | |||
| 4283f38698 | |||
| 2d49c0d1f3 | |||
| a7ca3817db | |||
| 1f044547ee | |||
| 612fc47044 | |||
| 8959ff155b | |||
| dadf57cc8b | |||
| 764b6c61d9 | |||
| 582dadf787 | |||
| 12d97169d7 | |||
| c29cfa823d | |||
| e183a9694e | |||
| d6cb449011 | |||
| 7bf4ad30fc | |||
| b3936b96e5 | |||
| 44d0625e91 | |||
| c492cde048 | |||
| c2fa6cc94d | |||
| 464608025b | |||
| d653d2308b | |||
| a52b1f121c | |||
| 9edd8be520 | |||
| aa1d47600a | |||
| be7ec8b40e | |||
| 8e12dd9c17 | |||
| fee0f0dce0 | |||
| 0dd80e7b50 | |||
| 78d5b72081 | |||
| e0df865401 | |||
| 2abcbed67a | |||
| 02b9d0b2e6 | |||
| 927e181db7 | |||
| dc411b3175 | |||
| 1e870f0f0d | |||
| 3cd01598a5 | |||
| 3b6d683b7f | |||
| eeef763f6d | |||
| 76d3ec583d | |||
| 077d8b9247 | |||
| 92840b9f68 | |||
| bf60d5a041 | |||
| 56ffab045e | |||
| 496ee401d7 | |||
| f0d5b3b368 | |||
| 88072a56ea | |||
| 0d3a637389 | |||
| dc44f3c226 | |||
| 1029b0b97f | |||
| 84f8228b8c | |||
| 968e8f0121 | |||
| 9eb1da4568 | |||
| 315e79e9f0 | |||
| 363d0d4f41 | |||
| 5ac631a270 | |||
| 75fc882001 | |||
| d7cb213eeb | |||
| 568e0d297a | |||
| 8edf358739 | |||
| 40be3ed05d | |||
| 2c174d6b3b | |||
| 60ee465bf7 | |||
| 51210d6b95 | |||
| a6caa267bd | |||
| cdb3e9dc0d | |||
| f2f09767fb | |||
| eec31d7126 | |||
| 3c5ad753b6 | |||
| dd338b5567 | |||
| 1b15af713c | |||
| 89c5affc3b | |||
| 2bba69f633 | |||
| 4403f136b7 | |||
| f7c1c638bb | |||
| f2d7bbe0e9 | |||
| 87468cffce | |||
| 3f7e3a714e | |||
| 38a9caf159 | |||
| 500c8ab4b3 | |||
| c4ad97d555 |
@@ -1,4 +1,52 @@
|
||||
|
||||
3.0.2 / 2012-11-08
|
||||
==================
|
||||
|
||||
* add OPTIONS to cors example. Closes #1398
|
||||
* fix route chaining regression. Closes #1397
|
||||
|
||||
3.0.1 / 2012-11-01
|
||||
==================
|
||||
|
||||
* update connect
|
||||
|
||||
3.0.0 / 2012-10-23
|
||||
==================
|
||||
|
||||
* add `make clean`
|
||||
* add "Basic" check to req.auth
|
||||
* add `req.auth` test coverage
|
||||
* add cb && cb(payload) to `res.jsonp()`. Closes #1374
|
||||
* add backwards compat for `res.redirect()` status. Closes #1336
|
||||
* add support for `res.json()` to retain previously defined Content-Types. Closes #1349
|
||||
* update connect
|
||||
* change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382
|
||||
* remove non-primitive string support for `res.send()`
|
||||
* fix view-locals example. Closes #1370
|
||||
* fix route-separation example
|
||||
|
||||
3.0.0rc5 / 2012-09-18
|
||||
==================
|
||||
|
||||
* update connect
|
||||
* add redis search example
|
||||
* add static-files example
|
||||
* add "x-powered-by" setting (`app.disable('x-powered-by')`)
|
||||
* add "application/octet-stream" redirect Accept test case. Closes #1317
|
||||
|
||||
3.0.0rc4 / 2012-08-30
|
||||
==================
|
||||
|
||||
* add `res.jsonp()`. Closes #1307
|
||||
* add "verbose errors" option to error-pages example
|
||||
* add another route example to express(1) so people are not so confused
|
||||
* add redis online user activity tracking example
|
||||
* update connect dep
|
||||
* fix etag quoting. Closes #1310
|
||||
* fix error-pages 404 status
|
||||
* fix jsonp callback char restrictions
|
||||
* remove old OPTIONS default response
|
||||
|
||||
3.0.0rc3 / 2012-08-13
|
||||
==================
|
||||
|
||||
|
||||
+5
-1
@@ -26,4 +26,8 @@ lib-cov:
|
||||
benchmark:
|
||||
@./support/bench
|
||||
|
||||
.PHONY: test test-unit test-acceptance benchmark
|
||||
clean:
|
||||
rm -f coverage.html
|
||||
rm -fr lib-cov
|
||||
|
||||
.PHONY: test test-unit test-acceptance benchmark clean
|
||||
|
||||
+4
-4
@@ -1,4 +1,3 @@
|
||||
|
||||

|
||||
|
||||
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [](http://travis-ci.org/visionmedia/express)
|
||||
@@ -74,8 +73,9 @@ app.listen(3000);
|
||||
|
||||
## Viewing Examples
|
||||
|
||||
First install the dev dependencies to install all the example / test suite deps:
|
||||
Clone the Express repo, then install the dev dependencies to install all the example / test suite deps:
|
||||
|
||||
$ git clone git://github.com/visionmedia/express.git --depth 1
|
||||
$ cd express
|
||||
$ npm install
|
||||
|
||||
@@ -107,7 +107,7 @@ authors:
|
||||
54 Aaron Heckmann 1.5%
|
||||
34 csausdev 1.0%
|
||||
26 ciaranj 0.7%
|
||||
21 Robert Sköld 0.6%
|
||||
21 Robert Sköld 0.6%
|
||||
6 Guillermo Rauch 0.2%
|
||||
3 Dav Glass 0.1%
|
||||
3 Nick Poulden 0.1%
|
||||
@@ -153,7 +153,7 @@ authors:
|
||||
1 Jonathan Zacsh 0.0%
|
||||
1 Justin Lilly 0.0%
|
||||
1 Ken Sato 0.0%
|
||||
1 Maciej Małecki 0.0%
|
||||
1 Maciej Małecki 0.0%
|
||||
1 Masahiro Hayashi 0.0%
|
||||
```
|
||||
|
||||
|
||||
@@ -54,6 +54,21 @@ var index = [
|
||||
, '};'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* Routes users template.
|
||||
*/
|
||||
|
||||
var users = [
|
||||
''
|
||||
, '/*'
|
||||
, ' * GET users listing.'
|
||||
, ' */'
|
||||
, ''
|
||||
, 'exports.list = function(req, res){'
|
||||
, ' res.send("respond with a resource");'
|
||||
, '};'
|
||||
].join(eol);
|
||||
|
||||
/**
|
||||
* Jade layout template.
|
||||
*/
|
||||
@@ -195,6 +210,7 @@ var app = [
|
||||
, ''
|
||||
, 'var express = require(\'express\')'
|
||||
, ' , routes = require(\'./routes\')'
|
||||
, ' , user = require(\'./routes/user\')'
|
||||
, ' , http = require(\'http\')'
|
||||
, ' , path = require(\'path\');'
|
||||
, ''
|
||||
@@ -217,6 +233,7 @@ var app = [
|
||||
, '});'
|
||||
, ''
|
||||
, 'app.get(\'/\', routes.index);'
|
||||
, 'app.get(\'/users\', user.list);'
|
||||
, ''
|
||||
, 'http.createServer(app).listen(app.get(\'port\'), function(){'
|
||||
, ' console.log("Express server listening on port " + app.get(\'port\'));'
|
||||
@@ -280,6 +297,7 @@ function createApplicationAt(path) {
|
||||
|
||||
mkdir(path + '/routes', function(){
|
||||
write(path + '/routes/index.js', index);
|
||||
write(path + '/routes/user.js', users);
|
||||
});
|
||||
|
||||
mkdir(path + '/views', function(){
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../../lib/express')
|
||||
var express = require('../..')
|
||||
, hash = require('./pass').hash;
|
||||
|
||||
var app = module.exports = express();
|
||||
@@ -50,6 +49,7 @@ hash('foobar', function(err, salt, hash){
|
||||
|
||||
|
||||
// Authenticate using our plain-object database of doom!
|
||||
|
||||
function authenticate(name, pass, fn) {
|
||||
if (!module.parent) console.log('authenticating %s:%s', name, pass);
|
||||
var user = users[name];
|
||||
@@ -79,7 +79,7 @@ app.get('/', function(req, res){
|
||||
});
|
||||
|
||||
app.get('/restricted', restrict, function(req, res){
|
||||
res.send('Wahoo! restricted area');
|
||||
res.send('Wahoo! restricted area, click to <a href="/logout">logout</a>');
|
||||
});
|
||||
|
||||
app.get('/logout', function(req, res){
|
||||
@@ -91,11 +91,6 @@ app.get('/logout', function(req, res){
|
||||
});
|
||||
|
||||
app.get('/login', function(req, res){
|
||||
if (req.session.user) {
|
||||
req.session.success = 'Authenticated as ' + req.session.user.name
|
||||
+ ' click to <a href="/logout">logout</a>. '
|
||||
+ ' You may now access <a href="/restricted">/restricted</a>.';
|
||||
}
|
||||
res.render('login');
|
||||
});
|
||||
|
||||
@@ -109,6 +104,9 @@ app.post('/login', function(req, res){
|
||||
// in the session store to be retrieved,
|
||||
// or in this case the entire user object
|
||||
req.session.user = user;
|
||||
req.session.success = 'Authenticated as ' + user.name
|
||||
+ ' click to <a href="/logout">logout</a>. '
|
||||
+ ' You may now access <a href="/restricted">/restricted</a>.';
|
||||
res.redirect('back');
|
||||
});
|
||||
} else {
|
||||
@@ -123,4 +121,4 @@ app.post('/login', function(req, res){
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express started on port 3000');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Authentication Example</title>
|
||||
<title><%= title %></title>
|
||||
<style>
|
||||
body {
|
||||
padding: 50px;
|
||||
@@ -16,6 +16,3 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<%- body %>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,3 +1,7 @@
|
||||
|
||||
<% var title = 'Authentication Example' %>
|
||||
<% include head %>
|
||||
|
||||
<h1>Login</h1>
|
||||
<%- message %>
|
||||
Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj" and "foobar".
|
||||
@@ -13,4 +17,6 @@ Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj"
|
||||
<p>
|
||||
<input type="submit" value="Login">
|
||||
</p>
|
||||
</form>
|
||||
</form>
|
||||
|
||||
<% include foot %>
|
||||
|
||||
@@ -26,6 +26,7 @@ api.all('*', function(req, res, next){
|
||||
res.set('Access-Control-Allow-Methods', 'GET, POST');
|
||||
res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
|
||||
// res.set('Access-Control-Allow-Max-Age', 3600);
|
||||
if ('OPTIONS' == req.method) return res.send(200);
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
@@ -31,16 +31,20 @@ app.set('view engine', 'html');
|
||||
|
||||
// Dummy users
|
||||
var users = [
|
||||
{ name: 'tobi', email: 'tobi@learnboost.com' }
|
||||
, { name: 'loki', email: 'loki@learnboost.com' }
|
||||
, { name: 'jane', email: 'jane@learnboost.com' }
|
||||
{ name: 'tobi', email: 'tobi@learnboost.com' },
|
||||
{ name: 'loki', email: 'loki@learnboost.com' },
|
||||
{ name: 'jane', email: 'jane@learnboost.com' }
|
||||
];
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('users', { users: users });
|
||||
res.render('users', {
|
||||
users: users,
|
||||
title: "EJS example",
|
||||
header: "Some users"
|
||||
});
|
||||
});
|
||||
|
||||
if (!module.parent) {
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title> <%= title %> </title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding: 50px;
|
||||
font: 13px Helvetica, Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -1,6 +1,10 @@
|
||||
<% include header.html %>
|
||||
|
||||
<h1>Users</h1>
|
||||
<ul id="users">
|
||||
<% users.forEach(function(user){ %>
|
||||
<li><%= user.name %> <%= user.email %></li>
|
||||
<li><%= user.name %> <<%= user.email %>></li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<% include footer.html %>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
@@ -7,9 +6,21 @@ var express = require('../../')
|
||||
, app = module.exports = express()
|
||||
, silent = 'test' == process.env.NODE_ENV;
|
||||
|
||||
// general config
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
// our custom "verbose errors" setting
|
||||
// which we can use in the templates
|
||||
// via settings['verbose errors']
|
||||
app.enable('verbose errors');
|
||||
|
||||
// disable them in production
|
||||
// use $ NODE_ENV=production node examples/error-pages
|
||||
if ('production' == app.settings.env) {
|
||||
app.disable('verbose errors');
|
||||
}
|
||||
|
||||
app.use(express.favicon());
|
||||
|
||||
silent || app.use(express.logger('dev'));
|
||||
@@ -32,9 +43,10 @@ app.use(app.router);
|
||||
// $ curl http://localhost:3000/notfound -H "Accept: text/plain"
|
||||
|
||||
app.use(function(req, res, next){
|
||||
res.status(404);
|
||||
|
||||
// respond with html page
|
||||
if (req.accepts('html')) {
|
||||
res.status(404);
|
||||
res.render('404', { url: req.url });
|
||||
return;
|
||||
}
|
||||
@@ -76,16 +88,21 @@ app.get('/', function(req, res){
|
||||
});
|
||||
|
||||
app.get('/404', function(req, res, next){
|
||||
// trigger a 404 since no other middleware
|
||||
// will match /404 after this one, and we're not
|
||||
// responding here
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/403', function(req, res, next){
|
||||
// trigger a 403 error
|
||||
var err = new Error('not allowed!');
|
||||
err.status = 403;
|
||||
next(err);
|
||||
});
|
||||
|
||||
app.get('/500', function(req, res, next){
|
||||
// trigger a generic (500) error
|
||||
next(new Error('keyboard cat!'));
|
||||
});
|
||||
|
||||
|
||||
@@ -7,4 +7,7 @@ extends error
|
||||
|
||||
block content
|
||||
h1 Error: #{error.message}
|
||||
pre= error.stack
|
||||
if settings['verbose errors']
|
||||
pre= error.stack
|
||||
else
|
||||
p An error ocurred!
|
||||
@@ -8,8 +8,8 @@ block content
|
||||
| visit
|
||||
a(href="/500") 500
|
||||
li
|
||||
| visit
|
||||
| visit
|
||||
a(href="/404") 404
|
||||
li
|
||||
| visit
|
||||
| visit
|
||||
a(href='/403') 403
|
||||
@@ -1,3 +1,4 @@
|
||||
body {
|
||||
padding: 50px 80px;
|
||||
font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif;}
|
||||
font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
// first:
|
||||
// $ npm install redis online
|
||||
// $ redis-server
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../..')
|
||||
, online = require('online')
|
||||
, redis = require('redis')
|
||||
, db = redis.createClient();
|
||||
|
||||
// online
|
||||
|
||||
online = online(db);
|
||||
|
||||
// app
|
||||
|
||||
var app = express();
|
||||
|
||||
// activity tracking, in this case using
|
||||
// the UA string, you would use req.user.id etc
|
||||
|
||||
app.use(function(req, res, next){
|
||||
// fire-and-forget
|
||||
online.add(req.headers['user-agent']);
|
||||
next();
|
||||
});
|
||||
|
||||
/**
|
||||
* List helper.
|
||||
*/
|
||||
|
||||
function list(ids) {
|
||||
return '<ul>' + ids.map(function(id){
|
||||
return '<li>' + id + '</li>';
|
||||
}).join('') + '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* GET users online.
|
||||
*/
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
online.last(5, function(err, ids){
|
||||
if (err) return next(err);
|
||||
res.send('<p>Users online: ' + ids.length + '</p>' + list(ids));
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('listening on port 3000');
|
||||
@@ -11,9 +11,11 @@ var express = require('../..')
|
||||
|
||||
// Config
|
||||
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('view engine', 'jade');
|
||||
app.set('views', __dirname + '/views');
|
||||
app.use(express.logger('dev'));
|
||||
app.use(express.cookieParser());
|
||||
app.use(express.bodyParser());
|
||||
app.use(express.methodOverride());
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
|
||||
@@ -35,4 +37,4 @@ app.put('/user/:id/edit', user.update);
|
||||
app.get('/posts', post.list);
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
console.log('Express app started on port 3000');
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// Fake posts database
|
||||
|
||||
var posts = [
|
||||
{ title: 'Foo', body: 'some foo bar' }
|
||||
, { title: 'Foo bar', body: 'more foo bar' }
|
||||
, { title: 'Foo bar baz', body: 'more foo bar baz' }
|
||||
{ title: 'Foo', body: 'some foo bar' },
|
||||
{ title: 'Foo bar', body: 'more foo bar' },
|
||||
{ title: 'Foo bar baz', body: 'more foo bar baz' }
|
||||
];
|
||||
|
||||
exports.list = function(req, res){
|
||||
|
||||
@@ -11,10 +11,10 @@ a.edit {
|
||||
opacity: .3;
|
||||
}
|
||||
a.edit::before {
|
||||
content: '[ ';
|
||||
content: ' [';
|
||||
}
|
||||
a.edit::after {
|
||||
content: ' ]';
|
||||
content: ']';
|
||||
}
|
||||
dt {
|
||||
font-weight: bold;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Fake user database
|
||||
|
||||
var users = [
|
||||
{ name: 'TJ', email: 'tj@vision-media.ca' }
|
||||
, { name: 'Tobi', email: 'tobi@vision-media.ca' }
|
||||
{ name: 'TJ', email: 'tj@vision-media.ca' },
|
||||
{ name: 'Tobi', email: 'tobi@vision-media.ca' }
|
||||
];
|
||||
|
||||
exports.list = function(req, res){
|
||||
@@ -22,15 +22,15 @@ exports.load = function(req, res, next){
|
||||
|
||||
exports.view = function(req, res){
|
||||
res.render('users/view', {
|
||||
title: 'Viewing user ' + req.user.name
|
||||
, user: req.user
|
||||
title: 'Viewing user ' + req.user.name,
|
||||
user: req.user
|
||||
});
|
||||
};
|
||||
|
||||
exports.edit = function(req, res){
|
||||
res.render('users/edit', {
|
||||
title: 'Editing user ' + req.user.name
|
||||
, user: req.user
|
||||
title: 'Editing user ' + req.user.name,
|
||||
user: req.user
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<ul>
|
||||
<li>Visit the <a href="/users">users</a> page</li>
|
||||
<li>Visit the <a href="/posts">posts</a> page</li>
|
||||
</ul>
|
||||
@@ -0,0 +1,6 @@
|
||||
extends layout
|
||||
|
||||
block content
|
||||
ul
|
||||
li Visit the <a href="/users">users</a> page
|
||||
li Visit the <a href="/posts">posts</a> page
|
||||
@@ -1,9 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title><%= title %></title>
|
||||
<link href="/style.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<%- body %>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,6 @@
|
||||
html
|
||||
head
|
||||
title= title
|
||||
link(href="/style.css", rel="stylesheet")
|
||||
body
|
||||
block content
|
||||
@@ -1,7 +0,0 @@
|
||||
<h1>Posts</h1>
|
||||
<dl id="posts">
|
||||
<% posts.forEach(function(post){ %>
|
||||
<dt><%= post.title %></dt>
|
||||
<dd><%= post.body %></dd>
|
||||
<% }) %>
|
||||
</dl>
|
||||
@@ -0,0 +1,8 @@
|
||||
extends ../layout
|
||||
|
||||
block content
|
||||
h1 Posts
|
||||
dl#posts
|
||||
for post in posts
|
||||
dt= post.title
|
||||
dd= post.body
|
||||
@@ -1,9 +0,0 @@
|
||||
<h1>Editing <%= user.name %></h1>
|
||||
<div id="user">
|
||||
<form method="post">
|
||||
<input type="hidden" value="put" name="_method" />
|
||||
<p>Name: <input type="text" value="<%= user.name %>" name="user[name]"/></p>
|
||||
<p>Email: <input type="text" value="<%= user.email %>" name="user[email]"/></p>
|
||||
<p><input type="submit" value="Save" /></p>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,13 @@
|
||||
extends ../layout
|
||||
|
||||
block content
|
||||
h1 Editing #{user.name}
|
||||
#user
|
||||
form(method="post")
|
||||
input(type="hidden", value="put", name="_method")
|
||||
p Name:
|
||||
input(type="text", value= user.name, name="user[name]")
|
||||
p Email:
|
||||
input(type="text", value= user.email, name="user[email]")
|
||||
p
|
||||
input(type="submit", value="Save")
|
||||
@@ -1,9 +0,0 @@
|
||||
<h1>Users</h1>
|
||||
<ul id="users">
|
||||
<% users.forEach(function(user, id){ %>
|
||||
<li>
|
||||
<a href="/user/<%= id %>"><%= user.name %></a>
|
||||
<a class="edit" href="/user/<%= id %>/edit">edit</a>
|
||||
</li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
@@ -0,0 +1,9 @@
|
||||
extends ../layout
|
||||
|
||||
block content
|
||||
h1 Users
|
||||
#users
|
||||
for user, i in users
|
||||
li
|
||||
a(href="/user/#{i}")= user.name
|
||||
a.edit(href="/user/#{i}/edit") edit
|
||||
@@ -1,4 +0,0 @@
|
||||
<h1><%= user.name %></h1>
|
||||
<div id="user">
|
||||
<p>Email: <%= user.email %></p>
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
extends ../layout
|
||||
|
||||
block content
|
||||
h1= user.name
|
||||
#user
|
||||
p Email: #{user.email}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
var search = document.querySelector('[type=search]');
|
||||
var code = document.querySelector('pre');
|
||||
|
||||
search.addEventListener('keyup', function(){
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open('GET', '/search/' + search.value, true);
|
||||
xhr.onreadystatechange = function(){
|
||||
if (4 == xhr.readyState) {
|
||||
code.textContent = xhr.responseText;
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}, false);
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
// first:
|
||||
// $ npm install redis
|
||||
// $ redis-server
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../..')
|
||||
, redis = require('redis')
|
||||
, db = redis.createClient();
|
||||
|
||||
// npm install redis
|
||||
|
||||
var app = express();
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
app.set('views', __dirname);
|
||||
|
||||
// populate search
|
||||
|
||||
db.sadd('ferret', 'tobi');
|
||||
db.sadd('ferret', 'loki');
|
||||
db.sadd('ferret', 'jane');
|
||||
db.sadd('cat', 'manny');
|
||||
db.sadd('cat', 'luna');
|
||||
|
||||
/**
|
||||
* GET the search page.
|
||||
*/
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('search');
|
||||
});
|
||||
|
||||
/**
|
||||
* GET search for :query.
|
||||
*/
|
||||
|
||||
app.get('/search/:query?', function(req, res){
|
||||
var query = req.params.query;
|
||||
db.smembers(query, function(err, vals){
|
||||
if (err) return res.send(500);
|
||||
res.send(vals);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* GET client javascript. Here we use sendfile()
|
||||
* because serving __dirname with the static() middleware
|
||||
* would also mean serving our server "index.js" and the "search.jade"
|
||||
* template.
|
||||
*/
|
||||
|
||||
app.get('/client.js', function(req, res){
|
||||
res.sendfile(__dirname + '/client.js');
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('app listening on port 3000');
|
||||
@@ -0,0 +1,15 @@
|
||||
!!! 5
|
||||
html
|
||||
head
|
||||
title Search example
|
||||
style
|
||||
body {
|
||||
font: 14px "Helvetica Neue", Helvetica;
|
||||
padding: 50px;
|
||||
}
|
||||
body
|
||||
h2 Search
|
||||
p Try searching for "ferret" or "cat".
|
||||
input(type='search')
|
||||
pre
|
||||
script(src='client.js')
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
// first:
|
||||
// $ npm install redis
|
||||
// $ redis-server
|
||||
|
||||
var express = require('../..');
|
||||
|
||||
var app = express();
|
||||
@@ -25,4 +29,4 @@ app.get('/', function(req, res){
|
||||
});
|
||||
|
||||
app.listen(3000);
|
||||
console.log('Express app started on port 3000');
|
||||
console.log('Express app started on port 3000');
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
var express = require('../..');
|
||||
var app = express();
|
||||
|
||||
// log requests
|
||||
app.use(express.logger('dev'));
|
||||
|
||||
// express on its own has no notion
|
||||
// of a "file". The express.static()
|
||||
// middleware checks for a file matching
|
||||
// the `req.path` within the directory
|
||||
// that you pass it. In this case "GET /js/app.js"
|
||||
// will look for "./public/js/app.js".
|
||||
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
|
||||
// if you wanted to "prefix" you may use
|
||||
// the mounting feature of Connect, for example
|
||||
// "GET /static/js/app.js" instead of "GET /js/app.js".
|
||||
// The mount-path "/static" is simply removed before
|
||||
// passing control to the express.static() middleware,
|
||||
// thus it serves the file correctly by ignoring "/static"
|
||||
app.use('/static', express.static(__dirname + '/public'));
|
||||
|
||||
// if for some reason you want to serve files from
|
||||
// several directories, you can use express.static()
|
||||
// multiple times! Here we're passing "./public/css",
|
||||
// this will allow "GET /style.css" instead of "GET /css/style.css":
|
||||
app.use(express.static(__dirname + '/public/css'));
|
||||
|
||||
// this examples does not have any routes, however
|
||||
// you may `app.use(app.router)` before or after these
|
||||
// static() middleware. If placed before them your routes
|
||||
// will be matched BEFORE file serving takes place. If placed
|
||||
// after as shown here then file serving is performed BEFORE
|
||||
// any routes are hit:
|
||||
app.use(app.router);
|
||||
|
||||
app.listen(3000);
|
||||
console.log('listening on port 3000');
|
||||
console.log('try:');
|
||||
console.log(' GET /hello.txt');
|
||||
console.log(' GET /js/app.js');
|
||||
console.log(' GET /css/style.css');
|
||||
@@ -0,0 +1,3 @@
|
||||
body {
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
hey
|
||||
@@ -0,0 +1 @@
|
||||
foo
|
||||
@@ -101,11 +101,6 @@ app.get('/middleware-locals', count2, users2, function(req, res, next){
|
||||
res.render('user', { title: 'Users' });
|
||||
});
|
||||
|
||||
|
||||
app.get('/locals', function(req, res){
|
||||
res.render('user', { title: 'Users' });
|
||||
});
|
||||
|
||||
// keep in mind that middleware may be placed anywhere
|
||||
// and in various combinations, so if you have locals
|
||||
// that you wish to make available to all subsequent
|
||||
|
||||
+12
-14
@@ -9,12 +9,10 @@ var connect = require('connect')
|
||||
, debug = require('debug')('express:application')
|
||||
, locals = require('./utils').locals
|
||||
, View = require('./view')
|
||||
, url = require('url')
|
||||
, utils = connect.utils
|
||||
, path = require('path')
|
||||
, http = require('http')
|
||||
, join = path.join
|
||||
, fs = require('fs');
|
||||
, join = path.join;
|
||||
|
||||
/**
|
||||
* Application prototype.
|
||||
@@ -33,7 +31,6 @@ var app = exports = module.exports = {};
|
||||
*/
|
||||
|
||||
app.init = function(){
|
||||
var self = this;
|
||||
this.cache = {};
|
||||
this.settings = {};
|
||||
this.engines = {};
|
||||
@@ -51,6 +48,7 @@ app.defaultConfiguration = function(){
|
||||
var self = this;
|
||||
|
||||
// default settings
|
||||
this.enable('x-powered-by');
|
||||
this.set('env', process.env.NODE_ENV || 'development');
|
||||
debug('booting in %s mode', this.get('env'));
|
||||
|
||||
@@ -82,7 +80,7 @@ app.defaultConfiguration = function(){
|
||||
this.locals.settings = this.settings;
|
||||
|
||||
// default configuration
|
||||
this.enable('jsonp callback');
|
||||
this.set('views', process.cwd() + '/views');
|
||||
this.set('jsonp callback name', 'callback');
|
||||
|
||||
this.configure('development', function(){
|
||||
@@ -105,7 +103,7 @@ app.defaultConfiguration = function(){
|
||||
*/
|
||||
|
||||
app.use = function(route, fn){
|
||||
var app, home, handle;
|
||||
var app, handle;
|
||||
|
||||
// default route to '/'
|
||||
if ('string' != typeof route) fn = route, route = '/';
|
||||
@@ -409,8 +407,9 @@ methods.forEach(function(method){
|
||||
if ('get' == method && 1 == arguments.length) return this.set(path);
|
||||
var args = [method].concat([].slice.call(arguments));
|
||||
if (!this._usedRouter) this.use(this.router);
|
||||
return this._router.route.apply(this._router, args);
|
||||
}
|
||||
this._router.route.apply(this._router, args);
|
||||
return this;
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -453,8 +452,7 @@ app.del = app.delete;
|
||||
*/
|
||||
|
||||
app.render = function(name, options, fn){
|
||||
var self = this
|
||||
, opts = {}
|
||||
var opts = {}
|
||||
, cache = this.cache
|
||||
, engines = this.engines
|
||||
, view;
|
||||
@@ -484,9 +482,9 @@ app.render = function(name, options, fn){
|
||||
// view
|
||||
if (!view) {
|
||||
view = new View(name, {
|
||||
defaultEngine: this.get('view engine')
|
||||
, root: this.get('views') || process.cwd() + '/views'
|
||||
, engines: engines
|
||||
defaultEngine: this.get('view engine'),
|
||||
root: this.get('views'),
|
||||
engines: engines
|
||||
});
|
||||
|
||||
if (!view.path) {
|
||||
@@ -522,7 +520,7 @@ app.render = function(name, options, fn){
|
||||
* , app = express();
|
||||
*
|
||||
* http.createServer(app).listen(80);
|
||||
* http.createServer({ ... }, app).listen(443);
|
||||
* https.createServer({ ... }, app).listen(443);
|
||||
*
|
||||
* @return {http.Server}
|
||||
* @api public
|
||||
|
||||
+2
-3
@@ -8,7 +8,6 @@ var connect = require('connect')
|
||||
, Router = require('./router')
|
||||
, req = require('./request')
|
||||
, res = require('./response')
|
||||
, send = require('send')
|
||||
, utils = connect.utils;
|
||||
|
||||
/**
|
||||
@@ -21,13 +20,13 @@ exports = module.exports = createApplication;
|
||||
* Framework version.
|
||||
*/
|
||||
|
||||
exports.version = '3.0.0rc3';
|
||||
exports.version = '3.0.2';
|
||||
|
||||
/**
|
||||
* Expose mime.
|
||||
*/
|
||||
|
||||
exports.mime = send.mime;
|
||||
exports.mime = connect.mime;
|
||||
|
||||
/**
|
||||
* Create an express application.
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ var utils = require('./utils');
|
||||
exports.init = function(app){
|
||||
return function expressInit(req, res, next){
|
||||
req.app = res.app = app;
|
||||
res.setHeader('X-Powered-By', 'Express');
|
||||
if (app.settings['x-powered-by']) res.setHeader('X-Powered-By', 'Express');
|
||||
req.res = res;
|
||||
res.req = req;
|
||||
req.next = next;
|
||||
|
||||
+6
-4
@@ -377,18 +377,20 @@ req.__defineGetter__('ips', function(){
|
||||
* req.auth
|
||||
* // => { username: 'tobi', password: 'hello' }
|
||||
*
|
||||
* @return {Object}
|
||||
* @return {Object} or undefined
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.__defineGetter__('auth', function(){
|
||||
// missing
|
||||
var auth = this.get('Authorization');
|
||||
if (!auth) return {};
|
||||
if (!auth) return;
|
||||
|
||||
// malformed
|
||||
auth = auth.split(' ')[1];
|
||||
if (!auth) return {};
|
||||
var parts = auth.split(' ');
|
||||
if ('basic' != parts[0].toLowerCase()) return;
|
||||
if (!parts[1]) return;
|
||||
auth = parts[1];
|
||||
|
||||
// credentials
|
||||
auth = new Buffer(auth, 'base64').toString().split(':');
|
||||
|
||||
+66
-27
@@ -2,18 +2,18 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var fs = require('fs')
|
||||
, http = require('http')
|
||||
var http = require('http')
|
||||
, path = require('path')
|
||||
, connect = require('connect')
|
||||
, utils = connect.utils
|
||||
, sign = require('cookie-signature').sign
|
||||
, normalizeType = require('./utils').normalizeType
|
||||
, normalizeTypes = require('./utils').normalizeTypes
|
||||
, etag = require('./utils').etag
|
||||
, statusCodes = http.STATUS_CODES
|
||||
, send = connect.static.send
|
||||
, cookie = require('cookie')
|
||||
, send = require('send')
|
||||
, crc = require('crc')
|
||||
, mime = connect.mime
|
||||
, basename = path.basename
|
||||
, extname = path.extname
|
||||
@@ -94,9 +94,6 @@ res.send = function(body){
|
||||
}
|
||||
}
|
||||
|
||||
// convert string objects to primitives
|
||||
if (body instanceof String) body = body.toString();
|
||||
|
||||
switch (typeof body) {
|
||||
// response status
|
||||
case 'number':
|
||||
@@ -133,9 +130,9 @@ res.send = function(body){
|
||||
// ETag support
|
||||
// TODO: W/ support
|
||||
if (len > 1024) {
|
||||
if (!this.get('ETag')) this.set('ETag', Buffer.isBuffer(body)
|
||||
? crc.buffer.crc32(body)
|
||||
: crc.crc32(body));
|
||||
if (!this.get('ETag')) {
|
||||
this.set('ETag', etag(body));
|
||||
}
|
||||
}
|
||||
|
||||
// freshness
|
||||
@@ -182,21 +179,62 @@ res.json = function(obj){
|
||||
}
|
||||
|
||||
// settings
|
||||
var app = this.app
|
||||
, jsonp = app.get('jsonp callback')
|
||||
, replacer = app.get('json replacer')
|
||||
, spaces = app.get('json spaces')
|
||||
, body = JSON.stringify(obj, replacer, spaces)
|
||||
, callback = this.req.query[app.get('jsonp callback name')];
|
||||
var app = this.app;
|
||||
var replacer = app.get('json replacer');
|
||||
var spaces = app.get('json spaces');
|
||||
var body = JSON.stringify(obj, replacer, spaces);
|
||||
|
||||
// content-type
|
||||
this.charset = this.charset || 'utf-8';
|
||||
this.get('Content-Type') || this.set('Content-Type', 'application/json');
|
||||
|
||||
return this.send(body);
|
||||
};
|
||||
|
||||
/**
|
||||
* Send JSON response with JSONP callback support.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* res.jsonp(null);
|
||||
* res.jsonp({ user: 'tj' });
|
||||
* res.jsonp(500, 'oh noes!');
|
||||
* res.jsonp(404, 'I dont have that');
|
||||
*
|
||||
* @param {Mixed} obj or status
|
||||
* @param {Mixed} obj
|
||||
* @return {ServerResponse}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.jsonp = function(obj){
|
||||
// allow status / body
|
||||
if (2 == arguments.length) {
|
||||
// res.json(body, status) backwards compat
|
||||
if ('number' == typeof arguments[1]) {
|
||||
this.statusCode = arguments[1];
|
||||
} else {
|
||||
this.statusCode = obj;
|
||||
obj = arguments[1];
|
||||
}
|
||||
}
|
||||
|
||||
// settings
|
||||
var app = this.app;
|
||||
var replacer = app.get('json replacer');
|
||||
var spaces = app.get('json spaces');
|
||||
var body = JSON.stringify(obj, replacer, spaces);
|
||||
var callback = this.req.query[app.get('jsonp callback name')];
|
||||
|
||||
// content-type
|
||||
this.charset = this.charset || 'utf-8';
|
||||
this.set('Content-Type', 'application/json');
|
||||
|
||||
// jsonp
|
||||
if (callback && jsonp) {
|
||||
if (callback) {
|
||||
this.set('Content-Type', 'text/javascript');
|
||||
body = callback.replace(/[^[]\w$.]/g, '') + '(' + body + ');';
|
||||
var cb = callback.replace(/[^\[\]\w$.]/g, '');
|
||||
body = cb + ' && ' + cb + '(' + body + ');';
|
||||
}
|
||||
|
||||
return this.send(body);
|
||||
@@ -410,12 +448,12 @@ res.type = function(type){
|
||||
*/
|
||||
|
||||
res.format = function(obj){
|
||||
var keys = Object.keys(obj)
|
||||
, req = this.req
|
||||
var req = this.req
|
||||
, next = req.next;
|
||||
|
||||
var fn = obj.default;
|
||||
if (fn) delete obj.default;
|
||||
var keys = Object.keys(obj);
|
||||
|
||||
var key = req.accepts(keys);
|
||||
|
||||
@@ -538,7 +576,7 @@ res.cookie = function(name, val, options){
|
||||
var signed = options.signed;
|
||||
if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies');
|
||||
if ('object' == typeof val) val = 'j:' + JSON.stringify(val);
|
||||
if (signed) val = 's:' + utils.sign(val, secret);
|
||||
if (signed) val = 's:' + sign(val, secret);
|
||||
if ('maxAge' in options) options.expires = new Date(Date.now() + options.maxAge);
|
||||
if (null == options.path) options.path = '/';
|
||||
this.set('Set-Cookie', cookie.serialize(name, String(val), options));
|
||||
@@ -558,6 +596,7 @@ res.cookie = function(name, val, options){
|
||||
* res.redirect('/foo/bar');
|
||||
* res.redirect('http://example.com');
|
||||
* res.redirect(301, 'http://example.com');
|
||||
* res.redirect('http://example.com', 301);
|
||||
* res.redirect('../login'); // /blog/post/1 -> /blog/login
|
||||
*
|
||||
* Mounting:
|
||||
@@ -587,8 +626,12 @@ res.redirect = function(url){
|
||||
|
||||
// allow status / url
|
||||
if (2 == arguments.length) {
|
||||
status = url;
|
||||
url = arguments[1];
|
||||
if ('number' == typeof url) {
|
||||
status = url;
|
||||
url = arguments[1];
|
||||
} else {
|
||||
status = arguments[1];
|
||||
}
|
||||
}
|
||||
|
||||
// setup redirect map
|
||||
@@ -608,10 +651,6 @@ res.redirect = function(url){
|
||||
} else if ('/' != url[0]) {
|
||||
url = path + '/' + url;
|
||||
}
|
||||
|
||||
// Absolute
|
||||
var host = req.get('Host');
|
||||
url = '//' + host + url;
|
||||
}
|
||||
|
||||
// Support text/{plain,html} by default
|
||||
@@ -675,4 +714,4 @@ res.render = function(view, options, fn){
|
||||
|
||||
// render
|
||||
app.render(view, options, fn);
|
||||
};
|
||||
};
|
||||
|
||||
+4
-43
@@ -5,8 +5,7 @@
|
||||
var Route = require('./route')
|
||||
, utils = require('../utils')
|
||||
, debug = require('debug')('express:router')
|
||||
, parse = require('connect').utils.parseUrl
|
||||
, methods = require('methods');
|
||||
, parse = require('connect').utils.parseUrl;
|
||||
|
||||
/**
|
||||
* Expose `Router` constructor.
|
||||
@@ -93,8 +92,7 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
, paramVal
|
||||
, route
|
||||
, keys
|
||||
, key
|
||||
, ret;
|
||||
, key;
|
||||
|
||||
// match next route
|
||||
function nextRoute(err) {
|
||||
@@ -104,9 +102,6 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
// match route
|
||||
req.route = route = self.matchRequest(req, i);
|
||||
|
||||
// implied OPTIONS
|
||||
if (!route && 'OPTIONS' == req.method) return self._options(req, res);
|
||||
|
||||
// no route
|
||||
if (!route) return next(err);
|
||||
debug('matched %s %s', route.method, route.path);
|
||||
@@ -162,7 +157,8 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
if (fn.length < 4) return callbacks(err);
|
||||
fn(err, req, res, callbacks);
|
||||
} else if (fn) {
|
||||
fn(req, res, callbacks);
|
||||
if (fn.length < 4) return fn(req, res, callbacks);
|
||||
callbacks();
|
||||
} else {
|
||||
nextRoute(err);
|
||||
}
|
||||
@@ -173,41 +169,6 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
})(0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Respond to __OPTIONS__ method.
|
||||
*
|
||||
* @param {IncomingMessage} req
|
||||
* @param {ServerResponse} res
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Router.prototype._options = function(req, res){
|
||||
var path = parse(req).pathname
|
||||
, body = this._optionsFor(path).join(',');
|
||||
res.set('Allow', body).send(body);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an array of HTTP verbs or "options" for `path`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Array}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Router.prototype._optionsFor = function(path){
|
||||
var self = this;
|
||||
return methods.filter(function(method){
|
||||
var routes = self.map[method];
|
||||
if (!routes || 'options' == method) return;
|
||||
for (var i = 0, len = routes.length; i < len; ++i) {
|
||||
if (routes[i].match(path)) return true;
|
||||
}
|
||||
}).map(function(method){
|
||||
return method.toUpperCase();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempt to match a route for `req`
|
||||
* with optional starting index of `i`
|
||||
|
||||
+16
-1
@@ -3,7 +3,22 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var mime = require('connect').mime;
|
||||
var mime = require('connect').mime
|
||||
, crc = require('crc');
|
||||
|
||||
/**
|
||||
* Return ETag for `body`.
|
||||
*
|
||||
* @param {String|Buffer} body
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.etag = function(body){
|
||||
return '"' + (Buffer.isBuffer(body)
|
||||
? crc.buffer.crc32(body)
|
||||
: crc.crc32(body)) + '"';
|
||||
};
|
||||
|
||||
/**
|
||||
* Make `locals()` bound to the given `obj`.
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "express",
|
||||
"description": "Sinatra inspired web development framework",
|
||||
"version": "3.0.0rc3",
|
||||
"version": "3.0.2",
|
||||
"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": "2.4.3",
|
||||
"connect": "2.6.2",
|
||||
"commander": "0.6.1",
|
||||
"range-parser": "0.0.4",
|
||||
"mkdirp": "0.3.3",
|
||||
@@ -18,7 +18,8 @@
|
||||
"crc": "0.2.0",
|
||||
"fresh": "0.1.0",
|
||||
"methods": "0.0.1",
|
||||
"send": "0.0.3",
|
||||
"send": "0.1.0",
|
||||
"cookie-signature": "0.0.1",
|
||||
"debug": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -43,7 +44,6 @@
|
||||
"app",
|
||||
"api"
|
||||
],
|
||||
"publishConfig": { "tag": "3.0" },
|
||||
"repository": "git://github.com/visionmedia/express",
|
||||
"main": "index",
|
||||
"bin": { "express": "./bin/express" },
|
||||
|
||||
+1
-3
@@ -16,8 +16,6 @@ app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade');
|
||||
app.locals.self = true;
|
||||
|
||||
var repo = require('../package.json');
|
||||
|
||||
app.get('/render', function(req, res){
|
||||
res.render('hello');
|
||||
});
|
||||
@@ -65,4 +63,4 @@ app.get('/match', function(req, res){
|
||||
res.send('Hello World\n');
|
||||
});
|
||||
|
||||
app.listen(8000);
|
||||
app.listen(8000);
|
||||
|
||||
@@ -10,9 +10,9 @@ describe('ejs', function(){
|
||||
.end(function(err, res){
|
||||
res.should.have.status(200);
|
||||
res.should.have.header('Content-Type', 'text/html; charset=utf-8');
|
||||
res.text.should.include('<li>tobi tobi@learnboost.com</li>');
|
||||
res.text.should.include('<li>loki loki@learnboost.com</li>');
|
||||
res.text.should.include('<li>jane jane@learnboost.com</li>');
|
||||
res.text.should.include('<li>tobi <tobi@learnboost.com></li>');
|
||||
res.text.should.include('<li>loki <loki@learnboost.com></li>');
|
||||
res.text.should.include('<li>jane <jane@learnboost.com></li>');
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('error-pages', function(){
|
||||
request(app)
|
||||
.get('/404')
|
||||
.set('Accept', 'text/plain')
|
||||
.expect(200)
|
||||
.expect(404)
|
||||
.expect('Not found', done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -57,8 +57,10 @@ describe('app.path()', function(){
|
||||
|
||||
describe('in development', function(){
|
||||
it('should disable "view cache"', function(){
|
||||
process.env.NODE_ENV = 'development';
|
||||
var app = express();
|
||||
app.enabled('view cache').should.be.false;
|
||||
process.env.NODE_ENV = 'test';
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
|
||||
describe('OPTIONS', function(){
|
||||
it('should default to the routes defined', function(done){
|
||||
var app = express();
|
||||
|
||||
app.del('/', function(){});
|
||||
app.get('/users', function(req, res){});
|
||||
app.put('/users', function(req, res){});
|
||||
|
||||
request(app)
|
||||
.options('/users')
|
||||
.expect('GET,PUT')
|
||||
.expect('Allow', 'GET,PUT', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('app.options()', function(){
|
||||
it('should override the default behavior', function(done){
|
||||
var app = express();
|
||||
|
||||
app.options('/users', function(req, res){
|
||||
res.set('Allow', 'GET');
|
||||
res.send('GET');
|
||||
});
|
||||
|
||||
app.get('/users', function(req, res){});
|
||||
app.put('/users', function(req, res){});
|
||||
|
||||
request(app)
|
||||
.options('/users')
|
||||
.expect('GET')
|
||||
.expect('Allow', 'GET', done);
|
||||
})
|
||||
})
|
||||
@@ -596,4 +596,9 @@ describe('app.router', function(){
|
||||
.get('/account/edit')
|
||||
.expect('editing user 12', done);
|
||||
})
|
||||
|
||||
it('should be chainable', function(){
|
||||
var app = express();
|
||||
app.get('/', function(){}).should.equal(app);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
|
||||
describe('app', function(){
|
||||
describe('.VERB()', function(){
|
||||
it('should only call an error handling routing callback when an error is propagated', function(done){
|
||||
var app = express();
|
||||
|
||||
var a = false;
|
||||
var b = false;
|
||||
var c = false;
|
||||
var d = false;
|
||||
|
||||
app.get('/', function(req, res, next){
|
||||
next(new Error('fabricated error'));
|
||||
}, function(req, res, next) {
|
||||
a = true;
|
||||
next();
|
||||
}, function(err, req, res, next){
|
||||
b = true;
|
||||
err.message.should.equal('fabricated error');
|
||||
next(err);
|
||||
}, function(err, req, res, next){
|
||||
c = true;
|
||||
err.message.should.equal('fabricated error');
|
||||
next();
|
||||
}, function(err, req, res, next){
|
||||
d = true;
|
||||
next();
|
||||
}, function(req, res){
|
||||
a.should.be.false;
|
||||
b.should.be.true;
|
||||
c.should.be.true;
|
||||
d.should.be.false;
|
||||
res.send(204);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(204, done);
|
||||
})
|
||||
})
|
||||
})
|
||||
+3
-2
@@ -1,6 +1,7 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('./support/http')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('exports', function(){
|
||||
it('should have .version', function(){
|
||||
@@ -14,7 +15,7 @@ describe('exports', function(){
|
||||
})
|
||||
|
||||
it('should expose .mime', function(){
|
||||
express.mime.should.equal(require('connect').mime);
|
||||
assert(express.mime == require('connect').mime, 'express.mime should be connect.mime');
|
||||
})
|
||||
|
||||
it('should expose Router', function(){
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.auth', function(){
|
||||
describe('when Authorization is missing', function(){
|
||||
it('should return undefined', function(done){
|
||||
var app = express();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send(req.auth || 'none');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('none', done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when Authorization is malformed', function(){
|
||||
it('should return undefined', function(done){
|
||||
var app = express();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send(req.auth || 'none');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Authorization', 'meow')
|
||||
.expect('none', done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when Authorization is not Basic', function(){
|
||||
it('should return undefined', function(done){
|
||||
var app = express();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send(req.auth || 'none');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Authorization', 'Meow dG9iaTpmZXJyZXQ')
|
||||
.expect('none', done)
|
||||
})
|
||||
})
|
||||
|
||||
it('should return .username and .password', function(done){
|
||||
var app = express();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send(req.auth || 'none');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Authorization', 'Basic dG9iaTpmZXJyZXQ=')
|
||||
.expect('{"username":"tobi","password":"ferret"}', done)
|
||||
})
|
||||
})
|
||||
})
|
||||
+26
-47
@@ -5,55 +5,16 @@ var express = require('../')
|
||||
|
||||
describe('res', function(){
|
||||
describe('.json(object)', function(){
|
||||
describe('when "jsonp callback" is enabled', function(){
|
||||
it('should respond with jsonp', function(done){
|
||||
var app = express();
|
||||
it('should not support jsonp callbacks', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.json({ count: 1 });
|
||||
});
|
||||
app.use(function(req, res){
|
||||
res.json({ foo: 'bar' });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback=something')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('something({"count":1});');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should allow renaming callback', function(done){
|
||||
var app = express();
|
||||
|
||||
app.set('jsonp callback name', 'clb');
|
||||
app.use(function(req, res){
|
||||
res.json({ count: 1 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?clb=something')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('something({"count":1});');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should allow []', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.json({ count: 1 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback=callbacks[123]')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('callbacks[123]({"count":1});');
|
||||
done();
|
||||
})
|
||||
})
|
||||
request(app)
|
||||
.get('/?callback=foo')
|
||||
.expect('{"foo":"bar"}', done);
|
||||
})
|
||||
|
||||
describe('when given primitives', function(){
|
||||
@@ -202,4 +163,22 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should not override previous Content-Types', function(done){
|
||||
var app = express();
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.type('application/vnd.example+json');
|
||||
res.json({ hello: 'world' });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.statusCode.should.equal(200);
|
||||
res.headers.should.have.property('content-type', 'application/vnd.example+json');
|
||||
res.text.should.equal('{"hello":"world"}');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.jsonp(object)', function(){
|
||||
it('should respond with jsonp', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ count: 1 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback=something')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('something && something({"count":1});');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should allow renaming callback', function(done){
|
||||
var app = express();
|
||||
|
||||
app.set('jsonp callback name', 'clb');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ count: 1 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?clb=something')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('something && something({"count":1});');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should allow []', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ count: 1 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback=callbacks[123]')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('callbacks[123] && callbacks[123]({"count":1});');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should disallow arbitrary js', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({});
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback=foo;bar()')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
|
||||
res.text.should.equal('foobar && foobar({});');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
describe('when given primitives', function(){
|
||||
it('should respond with json', 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; charset=utf-8');
|
||||
res.text.should.equal('null');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when given an array', function(){
|
||||
it('should respond with json', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp(['foo', 'bar', 'baz']);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('["foo","bar","baz"]');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when given an object', function(){
|
||||
it('should respond with json', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ name: 'tobi' });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('{"name":"tobi"}');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('"json replacer" setting', function(){
|
||||
it('should be passed to JSON.stringify()', function(done){
|
||||
var app = express();
|
||||
|
||||
app.set('json replacer', function(key, val){
|
||||
return '_' == key[0]
|
||||
? undefined
|
||||
: val;
|
||||
});
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ name: 'tobi', _id: 12345 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.text.should.equal('{"name":"tobi"}');
|
||||
done();
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
describe('"json spaces" setting', function(){
|
||||
it('should default to 2 in development', function(){
|
||||
process.env.NODE_ENV = 'development';
|
||||
var app = express();
|
||||
app.get('json spaces').should.equal(2);
|
||||
process.env.NODE_ENV = 'test';
|
||||
})
|
||||
|
||||
it('should be undefined otherwise', function(){
|
||||
var app = express();
|
||||
assert(undefined === app.get('json spaces'));
|
||||
})
|
||||
|
||||
it('should be passed to JSON.stringify()', function(done){
|
||||
var app = express();
|
||||
|
||||
app.set('json spaces', 2);
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ name: 'tobi', age: 2 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.text.should.equal('{\n "name": "tobi",\n "age": 2\n}');
|
||||
done();
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.json(status, object)', function(){
|
||||
it('should respond with json and set the .statusCode', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp(201, { id: 1 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.statusCode.should.equal(201);
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('{"id":1}');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.json(object, status)', function(){
|
||||
it('should respond with json and set the .statusCode for backwards compat', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ id: 1 }, 201);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.statusCode.should.equal(201);
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('{"id":1}');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
+28
-10
@@ -51,7 +51,7 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.set('Host', 'example.com')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('location', '//example.com/login');
|
||||
res.headers.should.have.property('location', '/login');
|
||||
done();
|
||||
})
|
||||
})
|
||||
@@ -69,7 +69,7 @@ describe('res', function(){
|
||||
.get('/post/1')
|
||||
.set('Host', 'example.com')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('location', '//example.com/post/1/./edit');
|
||||
res.headers.should.have.property('location', '/post/1/./edit');
|
||||
done();
|
||||
})
|
||||
})
|
||||
@@ -87,7 +87,7 @@ describe('res', function(){
|
||||
.get('/post/1')
|
||||
.set('Host', 'example.com')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('location', '//example.com/post/1/../new');
|
||||
res.headers.should.have.property('location', '/post/1/../new');
|
||||
done();
|
||||
})
|
||||
})
|
||||
@@ -105,7 +105,7 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.set('Host', 'example.com')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('location', '//example.com/login');
|
||||
res.headers.should.have.property('location', '/login');
|
||||
done();
|
||||
})
|
||||
})
|
||||
@@ -129,7 +129,7 @@ describe('res', function(){
|
||||
.get('/blog/admin')
|
||||
.set('Host', 'example.com')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('location', '//example.com/blog/admin/login');
|
||||
res.headers.should.have.property('location', '/blog/admin/login');
|
||||
done();
|
||||
})
|
||||
})
|
||||
@@ -150,7 +150,7 @@ describe('res', function(){
|
||||
.get('/blog')
|
||||
.set('Host', 'example.com')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('location', '//example.com/blog/admin/login');
|
||||
res.headers.should.have.property('location', '/blog/admin/login');
|
||||
done();
|
||||
})
|
||||
})
|
||||
@@ -171,7 +171,7 @@ describe('res', function(){
|
||||
.get('/blog')
|
||||
.set('Host', 'example.com')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('location', '//example.com/admin/login');
|
||||
res.headers.should.have.property('location', '/admin/login');
|
||||
done();
|
||||
})
|
||||
})
|
||||
@@ -196,7 +196,25 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('.redirect(url, status)', function(){
|
||||
it('should set the response status', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect('http://google.com', 303);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.statusCode.should.equal(303);
|
||||
res.headers.should.have.property('location', 'http://google.com');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the request method is HEAD', function(){
|
||||
it('should ignore the body', function(done){
|
||||
var app = express();
|
||||
@@ -245,7 +263,7 @@ describe('res', function(){
|
||||
.set('Host', 'http://example.com')
|
||||
.set('Accept', 'text/html')
|
||||
.end(function(err, res){
|
||||
res.text.should.equal('<p>Moved Temporarily. Redirecting to <a href="//http://example.com/<lame>">//http://example.com/<lame></a></p>');
|
||||
res.text.should.equal('<p>Moved Temporarily. Redirecting to <a href="/<lame>">/<lame></a></p>');
|
||||
done();
|
||||
})
|
||||
})
|
||||
@@ -281,7 +299,7 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Accept', 'foo/bar')
|
||||
.set('Accept', 'application/octet-stream')
|
||||
.end(function(err, res){
|
||||
res.should.have.status(302);
|
||||
res.headers.should.have.property('location', 'http://google.com');
|
||||
|
||||
@@ -125,7 +125,7 @@ describe('res', function(){
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('user.jade', {});
|
||||
res.render('user.jade');
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -140,7 +140,7 @@ describe('res', function(){
|
||||
|
||||
app.use(function(req, res){
|
||||
res.locals.user = { name: 'tobi' };
|
||||
res.render('user.jade', {});
|
||||
res.render('user.jade');
|
||||
});
|
||||
|
||||
request(app)
|
||||
|
||||
+15
-39
@@ -104,7 +104,7 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('ETag', '-1498647312')
|
||||
.expect('ETag', '"-1498647312"')
|
||||
.end(done);
|
||||
})
|
||||
|
||||
@@ -123,42 +123,6 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
|
||||
describe('.send(StringObj)', function(){
|
||||
it('should send as html', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send(new String('<p>hey</p>'));
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/html; charset=utf-8');
|
||||
res.text.should.equal('<p>hey</p>');
|
||||
res.statusCode.should.equal(200);
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should not override Content-Type', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.set('Content-Type', 'text/plain').send(new String('hey'));
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'text/plain');
|
||||
res.text.should.equal('hey');
|
||||
res.statusCode.should.equal(200);
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.send(Buffer)', function(){
|
||||
it('should send as octet-stream', function(done){
|
||||
var app = express();
|
||||
@@ -187,7 +151,7 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('ETag', '-1498647312')
|
||||
.expect('ETag', '"-1498647312"')
|
||||
.end(done);
|
||||
})
|
||||
|
||||
@@ -303,7 +267,7 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('If-None-Match', '-1498647312')
|
||||
.set('If-None-Match', '"-1498647312"')
|
||||
.expect(304, done);
|
||||
})
|
||||
|
||||
@@ -322,4 +286,16 @@ describe('res', function(){
|
||||
.expect('hey')
|
||||
.expect(500, done);
|
||||
})
|
||||
|
||||
it('should not support jsonp callbacks', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send({ foo: 'bar' });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback=foo')
|
||||
.expect('{"foo":"bar"}', done);
|
||||
})
|
||||
})
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário