Skip to content

Commit b4de385

Browse files
committed
add full express test suite
1 parent 1ebc34d commit b4de385

File tree

202 files changed

+21013
-191
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

202 files changed

+21013
-191
lines changed

package-lock.json

Lines changed: 1144 additions & 183 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
"ejs": "^3.1.10",
7070
"errorhandler": "^1.5.1",
7171
"exit-hook": "^2.2.1",
72-
"express": "^4.19.2",
72+
"express": "^4.21.1",
7373
"express-art-template": "^1.0.1",
7474
"express-async-errors": "^3.1.1",
7575
"express-dot-engine": "^1.0.8",
@@ -78,16 +78,23 @@
7878
"express-rate-limit": "^7.4.0",
7979
"express-session": "^1.18.0",
8080
"express-subdomain": "^1.0.6",
81+
"marked": "^14.1.3",
8182
"method-override": "^3.0.0",
83+
"mocha": "^10.7.3",
84+
"morgan": "^1.10.0",
8285
"multer": "^1.4.5-lts.1",
8386
"mustache-express": "^1.3.2",
8487
"pako": "^2.1.0",
88+
"pbkdf2-password": "^1.2.1",
8589
"pkg-pr-new": "^0.0.29",
8690
"pug": "^3.0.3",
8791
"response-time": "^2.3.2",
8892
"serve-index": "^1.9.1",
8993
"serve-static": "^1.16.2",
94+
"supertest": "^6.3.0",
9095
"swig": "^1.4.2",
91-
"vhost": "^3.0.2"
96+
"u-express-local": "file://./src/index.js",
97+
"vhost": "^3.0.2",
98+
"after": "0.8.2"
9299
}
93100
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Express examples
2+
3+
This page contains list of examples using Express.
4+
5+
- [auth](./auth) - Authentication with login and password
6+
- [content-negotiation](./content-negotiation) - HTTP content negotiation
7+
- [cookie-sessions](./cookie-sessions) - Working with cookie-based sessions
8+
- [cookies](./cookies) - Working with cookies
9+
- [downloads](./downloads) - Transferring files to client
10+
- [ejs](./ejs) - Working with Embedded JavaScript templating (ejs)
11+
- [error-pages](./error-pages) - Creating error pages
12+
- [error](./error) - Working with error middleware
13+
- [hello-world](./hello-world) - Simple request handler
14+
- [markdown](./markdown) - Markdown as template engine
15+
- [multi-router](./multi-router) - Working with multiple Express routers
16+
- [mvc](./mvc) - MVC-style controllers
17+
- [online](./online) - Tracking online user activity with `online` and `redis` packages
18+
- [params](./params) - Working with route parameters
19+
- [resource](./resource) - Multiple HTTP operations on the same resource
20+
- [route-map](./route-map) - Organizing routes using a map
21+
- [route-middleware](./route-middleware) - Working with route middleware
22+
- [route-separation](./route-separation) - Organizing routes per each resource
23+
- [search](./search) - Search API
24+
- [session](./session) - User sessions
25+
- [static-files](./static-files) - Serving static files
26+
- [vhost](./vhost) - Working with virtual hosts
27+
- [view-constructor](./view-constructor) - Rendering views dynamically
28+
- [view-locals](./view-locals) - Saving data in request object between middleware calls
29+
- [web-service](./web-service) - Simple API service
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
'use strict'
2+
3+
/**
4+
* Module dependencies.
5+
*/
6+
7+
var express = require("express");
8+
var hash = require('pbkdf2-password')()
9+
var path = require('path');
10+
var session = require('express-session');
11+
12+
var app = module.exports = express();
13+
14+
// config
15+
16+
app.set('view engine', 'ejs');
17+
app.set('views', path.join(__dirname, 'views'));
18+
19+
// middleware
20+
21+
app.use(express.urlencoded({ extended: false }))
22+
app.use(session({
23+
resave: false, // don't save session if unmodified
24+
saveUninitialized: false, // don't create session until something stored
25+
secret: 'shhhh, very secret'
26+
}));
27+
28+
// Session-persisted message middleware
29+
30+
app.use(function(req, res, next){
31+
var err = req.session.error;
32+
var msg = req.session.success;
33+
delete req.session.error;
34+
delete req.session.success;
35+
res.locals.message = '';
36+
if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
37+
if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
38+
next();
39+
});
40+
41+
// dummy database
42+
43+
var users = {
44+
tj: { name: 'tj' }
45+
};
46+
47+
// when you create a user, generate a salt
48+
// and hash the password ('foobar' is the pass here)
49+
50+
hash({ password: 'foobar' }, function (err, pass, salt, hash) {
51+
if (err) throw err;
52+
// store the salt & hash in the "db"
53+
users.tj.salt = salt;
54+
users.tj.hash = hash;
55+
});
56+
57+
58+
// Authenticate using our plain-object database of doom!
59+
60+
function authenticate(name, pass, fn) {
61+
if (!module.parent) console.log('authenticating %s:%s', name, pass);
62+
var user = users[name];
63+
// query the db for the given username
64+
if (!user) return fn(null, null)
65+
// apply the same algorithm to the POSTed password, applying
66+
// the hash against the pass / salt, if there is a match we
67+
// found the user
68+
hash({ password: pass, salt: user.salt }, function (err, pass, salt, hash) {
69+
if (err) return fn(err);
70+
if (hash === user.hash) return fn(null, user)
71+
fn(null, null)
72+
});
73+
}
74+
75+
function restrict(req, res, next) {
76+
if (req.session.user) {
77+
next();
78+
} else {
79+
req.session.error = 'Access denied!';
80+
res.redirect('/login');
81+
}
82+
}
83+
84+
app.get('/', function(req, res){
85+
res.redirect('/login');
86+
});
87+
88+
app.get('/restricted', restrict, function(req, res){
89+
res.send('Wahoo! restricted area, click to <a href="/logout">logout</a>');
90+
});
91+
92+
app.get('/logout', function(req, res){
93+
// destroy the user's session to log them out
94+
// will be re-created next request
95+
req.session.destroy(function(){
96+
res.redirect('/');
97+
});
98+
});
99+
100+
app.get('/login', function(req, res){
101+
res.render('login');
102+
});
103+
104+
app.post('/login', function (req, res, next) {
105+
authenticate(req.body.username, req.body.password, function(err, user){
106+
if (err) return next(err)
107+
if (user) {
108+
// Regenerate session when signing in
109+
// to prevent fixation
110+
req.session.regenerate(function(){
111+
// Store the user's primary key
112+
// in the session store to be retrieved,
113+
// or in this case the entire user object
114+
req.session.user = user;
115+
req.session.success = 'Authenticated as ' + user.name
116+
+ ' click to <a href="/logout">logout</a>. '
117+
+ ' You may now access <a href="/restricted">/restricted</a>.';
118+
res.redirect('back');
119+
});
120+
} else {
121+
req.session.error = 'Authentication failed, please check your '
122+
+ ' username and password.'
123+
+ ' (use "tj" and "foobar")';
124+
res.redirect('/login');
125+
}
126+
});
127+
});
128+
129+
/* istanbul ignore next */
130+
if (!module.parent) {
131+
app.listen(3000);
132+
console.log('Express started on port 3000');
133+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
</body>
2+
</html>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width,initial-scale=1">
6+
<title><%= title %></title>
7+
<style>
8+
body {
9+
padding: 50px;
10+
font: 13px Helvetica, Arial, sans-serif;
11+
}
12+
.error {
13+
color: red
14+
}
15+
.success {
16+
color: green;
17+
}
18+
</style>
19+
</head>
20+
<body>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
<%- include('head', { title: 'Authentication Example' }) -%>
3+
4+
<h1>Login</h1>
5+
<%- message %>
6+
Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj" and "foobar".
7+
<form method="post" action="/login">
8+
<p>
9+
<label for="username">Username:</label>
10+
<input type="text" name="username" id="username">
11+
</p>
12+
<p>
13+
<label for="password">Password:</label>
14+
<input type="text" name="password" id="password">
15+
</p>
16+
<p>
17+
<input type="submit" value="Login">
18+
</p>
19+
</form>
20+
21+
<%- include('foot') -%>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict'
2+
3+
var users = [];
4+
5+
users.push({ name: 'Tobi' });
6+
users.push({ name: 'Loki' });
7+
users.push({ name: 'Jane' });
8+
9+
module.exports = users;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict'
2+
3+
var express = require("express");
4+
var app = module.exports = express();
5+
var users = require('./db');
6+
7+
// so either you can deal with different types of formatting
8+
// for expected response in index.js
9+
app.get('/', function(req, res){
10+
res.format({
11+
html: function(){
12+
res.send('<ul>' + users.map(function(user){
13+
return '<li>' + user.name + '</li>';
14+
}).join('') + '</ul>');
15+
},
16+
17+
text: function(){
18+
res.send(users.map(function(user){
19+
return ' - ' + user.name + '\n';
20+
}).join(''));
21+
},
22+
23+
json: function(){
24+
res.json(users);
25+
}
26+
});
27+
});
28+
29+
// or you could write a tiny middleware like
30+
// this to add a layer of abstraction
31+
// and make things a bit more declarative:
32+
33+
function format(path) {
34+
var obj = require(path);
35+
return function(req, res){
36+
res.format(obj);
37+
};
38+
}
39+
40+
app.get('/users', format('./users'));
41+
42+
/* istanbul ignore next */
43+
if (!module.parent) {
44+
app.listen(3000);
45+
console.log('Express started on port 3000');
46+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict'
2+
3+
var users = require('./db');
4+
5+
exports.html = function(req, res){
6+
res.send('<ul>' + users.map(function(user){
7+
return '<li>' + user.name + '</li>';
8+
}).join('') + '</ul>');
9+
};
10+
11+
exports.text = function(req, res){
12+
res.send(users.map(function(user){
13+
return ' - ' + user.name + '\n';
14+
}).join(''));
15+
};
16+
17+
exports.json = function(req, res){
18+
res.json(users);
19+
};

0 commit comments

Comments
 (0)