DefinitelyTyped/express/express-tests.ts
2014-03-26 15:07:49 -04:00

1499 lines
40 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// <reference path="express.d.ts" />
import express = require('express');
var app = express();
//////////////////////////
var hash: any;
// config
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
// middleware
app.use(express.bodyParser());
app.use(express.cookieParser('shhhh, very secret'));
app.use(express.session());
// Session-persisted message middleware
app.use((req: express.Request, res: express.Response, next) => {
var err = req.session.error
, msg = req.session.success;
delete req.session.error;
delete req.session.success;
res.locals.message = '';
if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
next();
});
// dummy database
var users = <any>{
tj: { name: 'tj' }
};
// when you create a user, generate a salt
// and hash the password ('foobar' is the pass here)
hash('foobar', (err, salt, hash) => {
if (err) throw err;
// store the salt & hash in the "db"
users.tj.salt = salt;
users.tj.hash = 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];
// query the db for the given username
if (!user) return fn(new Error('cannot find user'));
// apply the same algorithm to the POSTed password, applying
// the hash against the pass / salt, if there is a match we
// found the user
hash(pass, user.salt, (err, hash) => {
if (err) return fn(err);
if (hash == user.hash) return fn(null, user);
fn(new Error('invalid password'));
});
}
function restrict(req: express.Request, res: express.Response, next?: Function) {
if (req.session.user) {
next();
} else {
req.session.error = 'Access denied!';
res.redirect('/login');
}
}
app.get('/', (req: express.Request, res: express.Response) => {
res.redirect('login');
});
app.get('/restricted', restrict, (req: express.Request, res: express.Response) => {
res.send('Wahoo! restricted area, click to <a href="/logout">logout</a>');
});
app.get('/logout', (req: express.Request, res: express.Response) => {
// destroy the user's session to log them out
// will be re-created next request
req.session.destroy(() => {
res.redirect('/');
});
});
app.get('/login', (req: express.Request, res: express.Response) => {
res.render('login');
});
app.post('/login', (req: express.Request, res: express.Response) => {
authenticate(req.body.username, req.body.password, (err, user) => {
if (user) {
// Regenerate session when signing in
// to prevent fixation
req.session.regenerate(() => {
// Store the user's primary key
// 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 {
req.session.error = 'Authentication failed, please check your '
+ ' username and password.'
+ ' (use "tj" and "foobar")';
res.redirect('login');
}
});
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
//////////////
app.set('views', __dirname);
app.set('view engine', 'jade');
var pets = [];
var n = 1000;
while (n--) {
pets.push({ name: 'Tobi', age: 2, species: 'ferret' });
pets.push({ name: 'Loki', age: 1, species: 'ferret' });
pets.push({ name: 'Jane', age: 6, species: 'ferret' });
}
app.use(express.logger('dev'));
app.get('/', (req: express.Request, res: express.Response) => {
res.render('pets', { pets: pets });
});
app.listen(3000);
console.log('Express listening on port 3000');
/////////////
app.get('/', (req: express.Request, res: express.Response) => {
res.format({
html: () => {
res.send('<ul>' + users.map(user => {
return '<li>' + user.name + '</li>';
}).join('') + '</ul>');
},
text: () => {
res.send(users.map(user => {
return ' - ' + user.name + '\n';
}).join(''));
},
json: () => {
res.json(users);
}
});
});
// or you could write a tiny middleware like
// this to abstract make things a bit more declarative:
function format(mod) {
var obj = require(mod);
return (req: express.Request, res: express.Response) => {
res.format(obj);
};
}
app.get('/users', format('./users'));
if (!module.parent) {
app.listen(3000);
console.log('listening on port 3000');
}
/////////////////////////
// add favicon() before logger() so
// GET /favicon.ico requests are not
// logged, because this middleware
// reponds to /favicon.ico and does not
// call next()
app.use(express.favicon());
// custom log format
if ('test' != process.env.NODE_ENV)
app.use(express.logger(':method :url'));
// parses request cookies, populating
// req.cookies and req.signedCookies
// when the secret is passed, used
// for signing the cookies.
app.use(express.cookieParser('my secret here'));
// parses json, x-www-form-urlencoded, and multipart/form-data
app.use(express.bodyParser());
app.get('/', (req: express.Request, res: express.Response) => {
if (req.cookies.remember) {
res.send('Remembered :). Click to <a href="/forget">forget</a>!.');
} else {
res.send('<form method="post"><p>Check to <label>'
+ '<input type="checkbox" name="remember"/> remember me</label> '
+ '<input type="submit" value="Submit"/>.</p></form>');
}
});
app.get('/forget', (req: express.Request, res: express.Response) => {
res.clearCookie('remember');
res.redirect('back');
});
app.post('/', (req: express.Request, res: express.Response) => {
var minute = 60000;
if (req.body.remember) res.cookie('remember', 1, { maxAge: minute });
res.redirect('back');
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
///////////////////
// ignore GET /favicon.ico
app.use(express.favicon());
// pass a secret to cookieParser() for signed cookies
app.use(express.cookieParser('manny is cool'));
// add req.session cookie support
app.use(express.cookieSession());
// do something with the session
app.use(count);
// custom middleware
function count(req: express.Request, res: express.Response) {
req.session.count = req.session.count || 0;
var n = req.session.count++;
res.send('viewed ' + n + ' times\n');
}
if (!module.parent) {
app.listen(3000);
console.log('Express server listening on port 3000');
}
///////////////
var api = app;
app.use(express.static(__dirname + '/public'));
// api middleware
api.use(express.logger('dev'));
api.use(express.bodyParser());
/**
* CORS support.
*/
api.all('*', (req: express.Request, res: express.Response, next) => {
if (!req.get('Origin')) return next();
// use "*" here to accept any origin
res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
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();
});
/**
* POST a user.
*/
api.post('/user', (req: express.Request, res: express.Response) => {
console.log(req.body);
res.send(201);
});
app.listen(3000);
api.listen(3001);
console.log('app listening on 3000');
console.log('api listening on 3001');
////////////////////
app.get('/', (req: express.Request, res: express.Response) => {
res.send('<ul>'
+ '<li>Download <a href="/files/amazing.txt">amazing.txt</a>.</li>'
+ '<li>Download <a href="/files/missing.txt">missing.txt</a>.</li>'
+ '</ul>');
});
// /files/* is accessed via req.params[0]
// but here we name it :file
app.get('/files/:file(*)', (req: express.Request, res: express.Response) => {
var file = req.params.file
, path = __dirname + '/files/' + file;
res.download(path);
});
// error handling middleware. Because it's
// below our routes, you will be able to
// "intercept" errors, otherwise Connect
// will respond with 500 "Internal Server Error".
app.use((err, req, res: express.Response, next) => {
// special-case 404s,
// remember you could
// render a 404 template here
if (404 == err.status) {
res.statusCode = 404;
res.send('Cant find that file, sorry!');
} else {
next(err);
}
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
///////////////////
// Register ejs as .html. If we did
// not call this, we would need to
// name our views foo.ejs instead
// of foo.html. The __express method
// is simply a function that engines
// use to hook into the Express view
// system by default, so if we want
// to change "foo.ejs" to "foo.html"
// we simply pass _any_ function, in this
// case `ejs.__express`.
app.engine('.html', require('ejs').__express);
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
// Without this you would need to
// supply the extension to res.render()
// ex: res.render('users.html').
app.set('view engine', 'html');
app.get('/', (req: express.Request, res: express.Response) => {
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');
}
////////////////////
var test: any;
if (!test) app.use(express.logger('dev'));
app.use(app.router);
// the error handler is strategically
// placed *below* the app.router; if it
// were above it would not receive errors
// from app.get() etc
app.use(error);
// error handling middleware have an arity of 4
// instead of the typical (req: express.Request, res: express.Response, next),
// otherwise they behave exactly like regular
// middleware, you may have several of them,
// in different orders etc.
function error(err, req, res: express.Response, next) {
// log it
if (!test) console.error(err.stack);
// respond with 500 "Internal Server Error".
res.send(500);
}
app.get('/', () => {
// Caught and passed down to the errorHandler middleware
throw new Error('something broke!');
});
app.get('/next', (req: express.Request, res: express.Response, next) => {
// We can also pass exceptions to next()
process.nextTick(() => {
next(new Error('oh no!'));
});
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
/////////////////////
var silent: any;
// 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'));
// "app.router" positions our routes
// above the middleware defined below,
// this means that Express will attempt
// to match & call routes _before_ continuing
// on, at which point we assume it's a 404 because
// no route has handled the request.
app.use(app.router);
// Since this is the last non-error-handling
// middleware use()d, we assume 404, as nothing else
// responded.
// $ curl http://localhost:3000/notfound
// $ curl http://localhost:3000/notfound -H "Accept: application/json"
// $ curl http://localhost:3000/notfound -H "Accept: text/plain"
app.use((req: express.Request, res: express.Response) => {
res.status(404);
// respond with html page
if (req.accepts('html')) {
res.render('404', { url: req.url });
return;
}
// respond with json
if (req.accepts('json')) {
res.send({ error: 'Not found' });
return;
}
// default to plain-text. send()
res.type('txt').send('Not found');
});
// error-handling middleware, take the same form
// as regular middleware, however they require an
// arity of 4, aka the signature (err, req, res: express.Response, next).
// when connect has an error, it will invoke ONLY error-handling
// middleware.
// If we were to next() here any remaining non-error-handling
// middleware would then be executed, or if we next(err) to
// continue passing the error, only error-handling middleware
// would remain being executed, however here
// we simply respond with an error page.
app.use((err, req, res: express.Response) => {
// we may use properties of the error object
// here and next(err) appropriately, or if
// we possibly recovered from the error, simply next().
res.status(err.status || 500);
res.render('500', { error: err });
});
// Routes
app.get('/', (req: express.Request, res: express.Response) => {
res.render('index.jade');
});
app.get('/404', (req: express.Request, res: express.Response, next) => {
// trigger a 404 since no other middleware
// will match /404 after this one, and we're not
// responding here
next();
});
app.get('/403', (req: express.Request, res: express.Response, next) => {
// trigger a 403 error
var err = <any>new Error('not allowed!');
err.status = 403;
next(err);
});
app.get('/500', (req: express.Request, res: express.Response, next) => {
// trigger a generic (500) error
next(new Error('keyboard cat!'));
});
if (!module.parent) {
app.listen(3000);
//silent ||  console.log('Express started on port 3000');
}
///////////////
var fs: any;
var md: any;
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
function User(name) {
this.private = 'heyyyy';
this.secret = 'something';
this.name = name;
this.id = 123;
}
// You'll probably want to do
// something like this so you
// dont expose "secret" data.
User.prototype.toJSON = function () {
return {
id: this.id,
name: this.name
};
};
app.use(express.logger('dev'));
// earlier on expose an object
// that we can tack properties on.
// all res.locals props are exposed
// to the templates, so "expose" will
// be present.
app.use((req: express.Request, res: express.Response, next) => {
res.locals.expose = {};
// you could alias this as req or res.expose
// to make it shorter and less annoying
next();
});
// pretend we loaded a user
app.use((req: express.Request, res: express.Response, next) => {
req.user = new User('Tobi');
next();
});
app.get('/', (req: express.Request, res: express.Response) => {
res.redirect('/user');
});
app.get('/user', (req: express.Request, res: express.Response) => {
// we only want to expose the user
// to the client for this route:
res.locals.expose.user = req.user;
res.render('page');
});
app.listen(3000);
console.log('app listening on port 3000');
///////////////////////
app.get('/', (req: express.Request, res: express.Response) => {
res.send('Hello World');
});
app.listen(3000);
console.log('Express started on port 3000');
////////////////////
// register .md as an engine in express view system
app.engine('md', (path, options, fn) => {
fs.readFile(path, 'utf8', (err, str) => {
if (err) return fn(err);
try {
var html = md(str);
html = html.replace(/\{([^}]+)\}/g, (_, name) => {
return options[name] || '';
});
fn(null, html);
} catch (err) {
fn(err);
}
});
});
app.set('views', __dirname + '/views');
// make it the default so we dont need .md
app.set('view engine', 'md');
app.get('/', (req: express.Request, res: express.Response) => {
res.render('index', { title: 'Markdown Example' });
});
app.get('/fail', (req: express.Request, res: express.Response) => {
res.render('missing', { title: 'Markdown Example' });
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
///////////////////////
var mformat: any;
// bodyParser in connect 2.x uses node-formidable to parse
// the multipart form data.
app.use(express.bodyParser());
app.get('/', (req: express.Request, res: express.Response) => {
res.send('<form method="post" enctype="multipart/form-data">'
+ '<p>Title: <input type="text" name="title" /></p>'
+ '<p>Image: <input type="file" name="image" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/', (req: express.Request, res: express.Response) => {
// the uploaded file can be found as `req.files.image` and the
// title field as `req.body.title`
res.send(mformat('\nuploaded %s (%d Kb) to %s as %s'
, req.files.image.name
, req.files.image.size / 1024 | 0
, req.files.image.path
, req.body.title));
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
//////////////////
// first:
// $ npm install redis online
// $ redis-server
/**
* Module dependencies.
*/
var online: any;
var db: any;
// online
online = online(db);
// activity tracking, in this case using
// the UA string, you would use req.user.id etc
app.use((req: express.Request, res: express.Response, next) => {
// fire-and-forget
online.add(req.headers['user-agent']);
next();
});
/**
* List helper.
*/
function list(ids) {
return '<ul>' + ids.map(id => {
return '<li>' + id + '</li>';
}).join('') + '</ul>';
}
/**
* GET users online.
*/
app.get('/', (req: express.Request, res: express.Response, next) => {
online.last(5, (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');
///////////////////
// Convert :to and :from to integers
app.param(['to', 'from'], (req: express.Request, res: express.Response, next, num, name) => {
req.params[name] = num = parseInt(num, 10);
if (isNaN(num)) {
next(new Error('failed to parseInt ' + num));
} else {
next();
}
});
// Load user by id
app.param('user', (req: express.Request, res: express.Response, next, id) => {
if (req.user = users[id]) {
next();
} else {
next(new Error('failed to find user'));
}
});
/**
* GET index.
*/
app.get('/', (req: express.Request, res: express.Response) => {
res.send('Visit /user/0 or /users/0-2');
});
/**
* GET :user.
*/
app.get('/user/:user', (req: express.Request, res: express.Response) => {
res.send('user ' + req.user.name);
});
/**
* GET users :from - :to.
*/
app.get('/users/:from-:to', (req: express.Request, res: express.Response) => {
var from = req.params.from
, to = req.params.to
, names = users.map(user => { return user.name; });
res.send('users ' + names.slice(from, to).join(', '));
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
//////////////////
// Ad-hoc example resource method
app.resource = function (path, obj) {
this.get(path, obj.index);
this.get(path + '/:a..:b.:format?', (req: express.Request, res: express.Response) => {
var a = parseInt(req.params.a, 10)
, b = parseInt(req.params.b, 10)
, format = req.params.format;
obj.range(req, res, a, b, format);
});
this.get(path + '/:id', obj.show);
this.del(path + '/:id', obj.destroy);
};
// Fake controller.
var FUser = {
index: (req: express.Request, res: express.Response) => {
res.send(users);
},
show: (req: express.Request, res: express.Response) => {
res.send(users[req.params.id] || { error: 'Cannot find user' });
},
destroy: (req: express.Request, res: express.Response) => {
var id = req.params.id;
var destroyed = id in users;
delete users[id];
res.send(destroyed ? 'destroyed' : 'Cannot find user');
},
range: (req: express.Request, res: express.Response, a, b, format) => {
var range = users.slice(a, b + 1);
switch (format) {
case 'json':
res.send(range);
break;
case 'html':
default:
var html = '<ul>' + range.map(user => {
return '<li>' + user.name + '</li>';
}).join('\n') + '</ul>';
res.send(html);
break;
}
}
};
// curl http://localhost:3000/users -- responds with all users
// curl http://localhost:3000/users/1 -- responds with user 1
// curl http://localhost:3000/users/4 -- responds with error
// curl http://localhost:3000/users/1..3 -- responds with several users
// curl -X DELETE http://localhost:3000/users/1 -- deletes the user
app.resource('/users', FUser);
app.get('/', (req: express.Request, res: express.Response) => {
res.send([
'<h1>Examples:</h1> <ul>'
, '<li>GET /users</li>'
, '<li>GET /users/1</li>'
, '<li>GET /users/3</li>'
, '<li>GET /users/1..3</li>'
, '<li>GET /users/1..3.json</li>'
, '<li>DELETE /users/4</li>'
, '</ul>'
].join('\n'));
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
/////////////////////
var verbose: any;
app.map = (a, route) => {
route = route || '';
for (var key in a) {
switch (typeof a[key]) {
// { '/path': { ... }}
case 'object':
app.map(a[key], route + key);
break;
// get: function(){ ... }
case 'function':
if (verbose) console.log('%s %s', key, route);
app[key](route, a[key]);
break;
}
}
};
var users2 = {
list: (req: express.Request, res: express.Response) => {
res.send('user list');
},
get: (req: express.Request, res: express.Response) => {
res.send('user ' + req.params.uid);
},
del: (req: express.Request, res: express.Response) => {
res.send('delete users');
}
};
var pets2 = {
list: (req: express.Request, res: express.Response) => {
res.send('user ' + req.params.uid + '\'s pets');
},
del: (req: express.Request, res: express.Response) => {
res.send('delete ' + req.params.uid + '\'s pet ' + req.params.pid);
}
};
app.map({
'/users': {
get: users2.list,
del: users2.del,
'/:uid': {
get: users.get ,
'/pets': {
get: pets2.list,
'/:pid': {
del: pets2.del
}
}
}
}
});
app.listen(3000);
///////////////////////////
// Example requests:
// curl http://localhost:3000/user/0
// curl http://localhost:3000/user/0/edit
// curl http://localhost:3000/user/1
// curl http://localhost:3000/user/1/edit (unauthorized since this is not you)
// curl -X DELETE http://localhost:3000/user/0 (unauthorized since you are not an admin)
function loadUser(req: express.Request, res: express.Response, next) {
// You would fetch your user from the db
var user = users[req.params.id];
if (user) {
req.user = user;
next();
} else {
next(new Error('Failed to load user ' + req.params.id));
}
}
function andRestrictToSelf(req: express.Request, res: express.Response, next) {
// If our authenticated user is the user we are viewing
// then everything is fine :)
if (req.authenticatedUser.id == req.user.id) {
next();
} else {
// You may want to implement specific exceptions
// such as UnauthorizedError or similar so that you
// can handle these can be special-cased in an error handler
// (view ./examples/pages for this)
next(new Error('Unauthorized'));
}
}
function andRestrictTo(role) {
return (req: express.Request, res: express.Response, next) => {
if (req.authenticatedUser.role == role) {
next();
} else {
next(new Error('Unauthorized'));
}
};
}
// Middleware for faux authentication
// you would of course implement something real,
// but this illustrates how an authenticated user
// may interact with middleware
app.use((req: express.Request, res: express.Response, next) => {
req.authenticatedUser = users[0];
next();
});
app.get('/', (req: express.Request, res: express.Response) => {
res.redirect('/user/0');
});
app.get('/user/:id', loadUser, (req: express.Request, res: express.Response) => {
res.send('Viewing user ' + req.user.name);
});
app.get('/user/:id/edit', loadUser, andRestrictToSelf, (req: express.Request, res: express.Response) => {
res.send('Editing user ' + req.user.name);
});
app.del('/user/:id', loadUser, andRestrictTo('admin'), (req: express.Request, res: express.Response) => {
res.send('Deleted user ' + req.user.name);
});
app.listen(3000);
console.log('Express app started on port 3000');
/////////////////////////
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('/', (req: express.Request, res: express.Response) => {
res.render('search');
});
/**
* GET search for :query.
*/
app.get('/search/:query?', (req: express.Request, res: express.Response) => {
var query = req.params.query;
db.smembers(query, (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', (req: express.Request, res: express.Response) => {
res.sendfile(__dirname + '/client.js');
});
app.listen(3000);
console.log('app listening on port 3000');
///////////////////
app.use(express.logger('dev'));
// Required by session() middleware
// pass the secret for signed cookies
// (required by session())
app.use(express.cookieParser('keyboard cat'));
// Populates req.session
app.use(express.session());
app.get('/', (req: express.Request, res: express.Response) => {
var body = '';
if (req.session.views) {
++req.session.views;
} else {
req.session.views = 1;
body += '<p>First time visiting? view this page in several browsers :)</p>';
}
res.send(body + '<p>viewed <strong>' + req.session.views + '</strong> times.</p>');
});
app.listen(3000);
console.log('Express app started on port 3000');
////////////////////////
// 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');
//////////////////
/*
edit /etc/vhosts:
127.0.0.1 foo.example.com
127.0.0.1 bar.example.com
127.0.0.1 example.com
*/
// Main app
var main = express();
main.use(express.logger('dev'));
main.get('/', (req: express.Request, res: express.Response) => {
res.send('Hello from main app!');
});
main.get('/:sub', (req: express.Request, res: express.Response) => {
res.send('requsted ' + req.params.sub);
});
// Redirect app
var redirect = express();
redirect.all('*', (req: express.Request, res: express.Response) => {
console.log(req.subdomains);
res.redirect('http://example.com:3000/' + req.subdomains[0]);
});
app.use(express.vhost('*.example.com', redirect));
app.use(express.vhost('example.com', main));
app.listen(3000);
console.log('Express app started on port 3000');
////////////////////
// create an error with .status. we
// can then use the property in our
// custom error handler (Connect repects this prop as well)
function merror(status, msg) {
var err = <any>new Error(msg);
err.status = status;
return err;
}
// if we wanted to supply more than JSON, we could
// use something similar to the content-negotiation
// example.
// here we validate the API key,
// by mounting this middleware to /api
// meaning only paths prefixed with "/api"
// will cause this middleware to be invoked
app.use('/api', (req, res: express.Response, next) => {
var key = req.query['api-key'];
// key isnt present
if (!key) return next(merror(400, 'api key required'));
// key is invalid
if (!~apiKeys.indexOf(key)) return next(merror(401, 'invalid api key'));
// all good, store req.key for route access
req.key = key;
next();
});
// position our routes above the error handling middleware,
// and below our API middleware, since we want the API validation
// to take place BEFORE our routes
app.use(app.router);
// middleware with an arity of 4 are considered
// error handling middleware. When you next(err)
// it will be passed through the defined middleware
// in order, but ONLY those with an arity of 4, ignoring
// regular middleware.
app.use((err, req, res: express.Response) => {
// whatever you want here, feel free to populate
// properties on `err` to treat it differently in here.
res.send(err.status || 500, { error: err.message });
});
// our custom JSON 404 middleware. Since it's placed last
// it will be the last middleware called, if all others
// invoke next() and do not respond.
app.use((req: express.Request, res: express.Response) => {
res.send(404, { error: "Lame, can't find that" });
});
// map of valid api keys, typically mapped to
// account info with some sort of database like redis.
// api keys do _not_ serve as authentication, merely to
// track API usage or help prevent malicious behavior etc.
var apiKeys = ['foo', 'bar', 'baz'];
// these two objects will serve as our faux database
var repos = [
{ name: 'express', url: 'http://github.com/visionmedia/express' }
, { name: 'stylus', url: 'http://github.com/learnboost/stylus' }
, { name: 'cluster', url: 'http://github.com/learnboost/cluster' }
];
var userRepos = {
tobi: [repos[0], repos[1]]
, loki: [repos[1]]
, jane: [repos[2]]
};
// we now can assume the api key is valid,
// and simply expose the data
app.get('/api/users', (req: express.Request, res: express.Response) => {
res.send(users);
});
app.get('/api/repos', (req: express.Request, res: express.Response) => {
res.send(repos);
});
app.get('/api/user/:name/repos', (req: express.Request, res: express.Response, next) => {
var name = req.params.name
, user = userRepos[name];
if (user) res.send(user);
else next();
});
if (!module.parent) {
app.listen(3000);
console.log('Express server listening on port 3000');
}
//////
var router = new express.Router();
router.get('/', function (req, resp, next?) {
resp.send('response from router');
resp.end();
if (next) {
next();
}
});
function test_general() {
app.use((err, req, res: express.Response) => {
console.error(err.stack);
res.send(500, 'Something broke!');
});
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(() => {});
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.get('/', (req: express.Request, res: express.Response) => {
res.send('hello world');
});
app.listen(3000);
app.set('title', 'My Site');
app.get('title');
app.enable('trust proxy');
app.get('trust proxy');
app.disable('trust proxy');
app.get('trust proxy');
app.enabled('trust proxy');
app.configure(() => {
app.set('title', 'My Application');
});
app.configure('development', () => {
app.set('db uri', 'localhost/dev');
});
app.configure('stage', 'production', () => {});
app.configure('1', '2', '3', () => {});
app.use((req: express.Request, res: express.Response) => {
res.send('Hello World');
});
app.engine('jade', require('jade').__express);
var User;
app.param('user', (req: express.Request, res: express.Response, next, id) => {
User.find(id, (err, user) =>{
if (err) {
next(err);
} else if (user) {
req.user = user;
next();
} else {
next(new Error('failed to load user'));
}
});
});
app.get(/^\/commits\/(\d+)(?:\.\.(\d+))?$/, (req: express.Request, res: express.Response) => {
var from = req.params[0];
var to = req.params[1] || 'HEAD';
res.send('commit range ' + from + '..' + to);
});
app.locals.title = 'My App';
app.locals.strftime = require('strftime');
var requireAuthentication;
var loadUser = () => {};
app.all('*', requireAuthentication, loadUser);
app.all('*', loadUser);
app.all('*', loadUser, loadUser, loadUser);
app.locals.title = 'My App';
app.locals.strftime = require('strftime');
app.locals({
title: 'My App',
phone: '1-250-858-9990',
email: 'me@myapp.com'
});
app.render('email', () => {});
app.render('email', { name: 'Tobi' }, () => {});
}
function test_request() {
var req: express.Request;
req.params.name;
req.params[0];
req.query.q;
req.body.user.name;
app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/my/files' }));
req.param('name');
req.route;
req.cookies.name;
req.signedCookies;
req.get('Content-Type');
req.accepts('html');
req.accepts(['html', 'json']);
req.is('html');
req.ip;
req.path;
req.host;
req.fresh;
req.stale;
req.xhr;
req.protocol;
req.subdomains;
req.originalUrl;
req.acceptedLanguages;
req.acceptedCharsets;
var charset;
req.acceptsCharset(charset);
var lang;
req.acceptsLanguage(lang);
req.session = null;
}
function test_response() {
var res: express.Response;
res.status(404).sendfile('path/to/404.png');
res.set('Content-Type', 'text/plain');
res.set({
'Content-Type': 'text/plain',
'Content-Length': '123',
'ETag': '12345'
});
res.get('Content-Type');
res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true });
res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true });
res.cookie('cart', { items: [1, 2, 3] });
res.cookie('cart', { items: [1, 2, 3] }, { maxAge: 900000 });;
res.cookie('name', 'tobi', { signed: true });
res.cookie('name', 'tobi', { path: '/admin' });
res.clearCookie('name', { path: '/admin' });
res.redirect('/foo/bar');
res.redirect('http://example.com');
res.redirect(301, 'http://example.com');
res.charset = 'value';
res.send('some html');
res.send(new Buffer('whoop'));
res.send({ some: 'json' });
res.send('some html');
res.send(404, 'Sorry, we cannot find that!');
res.send(500, { error: 'something blew up' });
res.send(200);
res.set('Content-Type', 'text/html');
res.send(new Buffer('some html'));
res.send('some html');
res.send({ user: 'tobi' });
res.send([1, 2, 3]);
res.json(null);
res.json({ user: 'tobi' });
res.json(500, { error: 'message' });
res.jsonp(null);
res.jsonp({ user: 'tobi' });
res.jsonp(500, { error: 'message' });
res.jsonp({ user: 'tobi' });
res.type('application/json');
res.format({
'text/plain': () => {
res.send('hey');
},
'text/html': () => {
res.send('hey');
},
'application/json': () => {
res.send({ message: 'hey' });
}
});
res.attachment();
res.attachment('path/to/logo.png');
app.get('/user/:uid/photos/:file', (req: express.Request, res: express.Response) => {
var uid = req.params.uid
, file = req.params.file;
req.user.mayViewFilesFrom(uid, yes => {
if (yes) {
res.sendfile('/uploads/' + uid + '/' + file);
} else {
res.send(403, 'Sorry! you cant see that.');
}
});
});
res.download('/report-12345.pdf');
res.download('/report-12345.pdf', 'report.pdf');
res.download('/report-12345.pdf', 'report.pdf', err => {
if (err) { } else { }
});
res.links({
next: 'http://api.example.com/users?page=2',
last: 'http://api.example.com/users?page=5'
});
app.use((req: express.Request, res: express.Response, next) => {
res.locals.user = req.user;
res.locals.authenticated = !req.user.anonymous;
next();
});
res.render('index', () => {});
res.render('user', { name: 'Tobi' }, () => {});
}
function test_middleware() {
app.use(express.basicAuth('username', 'password'));
app.use(express.basicAuth((user, pass) => {
return 'tj' == user && 'wahoo' == pass;
}));
app.use(express.bodyParser());
app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart());
app.use(express.logger());
app.use(express.compress());
app.use(express.methodOverride());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.cookieParser('some secret'));
app.use(express.cookieSession());
app.use(express.directory('public'));
app.use(express.static('public'));
app.use(router.middleware);
}
////////////////////
// make sure server can be shut down
var testShutdownServer = app.listen(0);
console.log('listening on port ' + testShutdownServer.address().port);
testShutdownServer.close();