typescript-closure-tools
Version:
Command-line tools to convert closure-style JSDoc annotations to typescript, and to convert typescript sources to closure externs files
1,499 lines (1,200 loc) • 41.5 kB
text/typescript
/// <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();