ExpressHigh performance web framework for node. | |
| lib/express/index.js |
Framework version.
|
exports.version = '1.0.0beta';
|
Module dependencies.
|
var Server = require('./server');
|
Shortcut for new Server(...) .
param: Function ... return: Server api: public
|
exports.createServer = function(){
return new Server(Array.prototype.slice.call(arguments));
};
|
View extensions.
|
require('./view');
require('./request');
require('./response');
|
| lib/express/request.js |
Module dependencies.
|
var http = require('http'),
utils = require('./utils'),
mime = require('connect/utils').mime;
|
Return request header or optional default.
Examples
req.header('Content-Type');
// => "text/plain"
req.header('content-type');
// => "text/plain"
req.header('Accept');
// => undefined
req.header('Accept', 'text/html');
// => "text/html"
|
http.IncomingMessage.prototype.header = function(name, defaultValue){
return this.headers[name.toLowerCase()] || defaultValue;
};
|
Check if the Accept header is present, and includes the given type .
When the Accept header is not present true is returned. Otherwise
the given type is matched by an exact match, and then subtypes. You
may pass the subtype such as "html" which is then converted internally
to "text/html" using the mime lookup table.
Examples
// Accept: text/html
req.accepts('html');
// => true
// Accept: text/*; application/json
req.accepts('html');
req.accepts('text/html');
req.accepts('text/plain');
req.accepts('application/json');
// => true
req.accepts('image/png');
req.accepts('png');
// => false
param: String type return: Boolean api: public
|
http.IncomingMessage.prototype.accepts = function(type){
var accept = this.header('Accept');
if (!accept || accept === '*
|
') {
return true;
} else if (type) {
// Allow "html" vs "text/html" etc
if (type.indexOf('/') < 0) {
type = mime.types['.' + type];
}
// Check if we have a direct match
if (accept.indexOf(type) >= 0) {
return true;
// Check if we have type/
} else {
type = type.split('/')[0] + '/';
return accept.indexOf(type) >= 0;
}
} else {
return false;
}
};
/**
Return the value of param name when present.
- Checks route placeholders, ex: /user/:id
- Checks query string params, ex: ?id=12
- Checks urlencoded body params, ex: id=12
To utilize urlencoded request bodies, req.body
should be an object. This can be done by using
the connect.bodyDecoder middleware.
param: String name return: String api: public
|
http.IncomingMessage.prototype.param = function(name){
if (this.params.path[name] !== undefined) {
return this.params.path[name];
}
if (this.params.get[name] !== undefined) {
return this.params.get[name];
}
if (this.body && this.body[name] !== undefined) {
return this.body[name];
}
};
|
Queue flash msg of the given type .
Examples
req.flash('info', 'email sent');
req.flash('error', 'email delivery failed');
req.flash('info', 'email re-sent');
// => 2
req.flash('info');
// => ['email sent', 'email re-sent']
req.flash('info');
// => []
req.flash();
// => { error: ['email delivery failed'], info: [] }
|
http.IncomingMessage.prototype.flash = function(type, msg){
var msgs = this.session.flash = this.session.flash || {};
if (type && msg) {
msg = utils.miniMarkdown(utils.htmlEscape(msg));
return (msgs[type] = msgs[type] || []).push(msg);
} else if (type) {
var arr = msgs[type];
delete msgs[type];
return arr || [];
} else {
this.session.flash = {};
return msgs;
}
};
function isxhr() {
return this.header('X-Requested-With', '').toLowerCase() === 'xmlhttprequest';
}
|
Check if the request was an XMLHttpRequest.
return: Boolean api: public
|
http.IncomingMessage.prototype.__defineGetter__('isXMLHttpRequest', isxhr);
http.IncomingMessage.prototype.__defineGetter__('xhr', isxhr);
|
| lib/express/response.js |
Module dependencies.
|
var fs = require('fs'),
http = require('http'),
path = require('path'),
utils = require('connect/utils'),
mime = require('connect/utils').mime,
Buffer = require('buffer').Buffer;
|
Send a response with the given body and optional headers and status code.
Examples
res.send(new Buffer('wahoo'));
res.send({ some: 'json' });
res.send('<p>some html</p>');
res.send('Sorry, cant find that', 404);
res.send('text', { 'Content-Type': 'text/plain' }, 201);
res.send(404);
|
http.ServerResponse.prototype.send = function(body, headers, status){
if (typeof headers === 'number') {
status = headers,
headers = null;
}
status = status || 200;
headers = headers || {};
switch (typeof body) {
case 'number':
if (!this.headers['Content-Type']) {
this.contentType('.txt');
}
body = http.STATUS_CODES[status = body];
break;
case 'string':
if (!this.headers['Content-Type']) {
this.contentType('.html');
}
break;
case 'object':
if (body instanceof Buffer) {
if (!this.headers['Content-Type']) {
this.contentType('.bin');
}
} else {
if (!this.headers['Content-Type']) {
this.contentType('.json');
}
body = JSON.stringify(body);
}
break;
}
if (!this.headers['Content-Length']) {
this.header('Content-Length', body instanceof Buffer
? body.length
: Buffer.byteLength(body));
}
utils.merge(this.headers, headers);
this.writeHead(status, this.headers);
this.end(body);
};
|
Transfer the given file . Automatically sets the Content-Type
response header, and responds with 404 / 500 appropriately.
param: String file api: public
|
http.ServerResponse.prototype.sendfile = function(file){
var self = this;
fs.readFile(file, function(err, buf){
if (err) {
self.send(err.errno === process.ENOENT
? 404
: 500);
} else {
self.contentType(file);
self.send(buf);
}
});
};
|
Set Content-Type response header passed through mime.type() .
Examples
var filename = 'path/to/image.png';
res.contentType(filename);
// res.headers['Content-Type'] is now "image/png"
|
http.ServerResponse.prototype.contentType = function(type){
return this.header('Content-Type', mime.type(type));
};
|
Set Content-Disposition header to attachment with optional filename .
param: String filename return: ServerResponse api: public
|
http.ServerResponse.prototype.attachment = function(filename){
this.header('Content-Disposition', filename
? 'attachment; filename="' + path.basename(filename) + '"'
: 'attachment');
return this;
};
|
Transfer the given file with optional filename as an attachment.
param: String file param: String filename return: Type api: public
|
http.ServerResponse.prototype.download = function(file, filename){
this.attachment(filename || file).sendfile(file);
};
|
Set or get response header name with optional val .
param: String name param: String val return: String api: public
|
http.ServerResponse.prototype.header = function(name, val){
return val === undefined
? this.headers[name]
: this.headers[name] = val;
};
|
Redirect to the given url with optional response status
defauling to 302.
The given url can also be the name of a mapped url, for
example by default express supports "back" which redirects
to the Referrer or Referer headers or the application's
"home" setting. Express also supports "home" out of the box,
which can be set via app.set('home', '/blog'); , and defaults
to '/'.
Redirect Mapping
To extend the redirect mapping capabilities that Express provides,
we may use the app.redirect() method:
app.redirect('google', 'http://google.com');
Now in a route we may call:
res.redirect('google');
We may also map dynamic redirects:
app.redirect('comments', function(req, res, params){
return '/post/' + params.id + '/comments';
});
So now we may do the following, and the redirect will dynamically adjust to
the context of the request. If we called this route with GET /post/12 our
redirect Location would be /post/12/comments.
app.get('/post/:id', function(req, res){
res.redirect('comments');
});
param: String url param: Number code api: public
|
http.ServerResponse.prototype.redirect = function(url, status){
var basePath = this.app.set('home') || '/';
var map = {
back: this.req.headers.referrer || this.req.headers.referer || basePath,
home: basePath
};
map.__proto__ = this.app.redirects;
var mapped = typeof map[url] === 'function'
? map[url](this.req, this, this.req.params.path)
: map[url];
this.writeHead(status || 302, { 'Location': mapped || url });
this.end();
};
|
| lib/express/server.js |
Module dependencies.
|
var sys = require('sys'),
url = require('url'),
view = require('./view'),
connect = require('connect'),
queryString = require('querystring'),
router = require('connect/middleware/router');
|
Initialize a new Server with optional middleware .
param: Array middleware api: public
|
var Server = exports = module.exports = function Server(middleware){
var self = this;
this.config = {};
this.settings = {};
this.redirects = {};
connect.Server.call(this, middleware || []);
this.use('/', function(req, res, next){
req.params = req.params || {};
req.params.get = {};
res.headers = {};
req.app = res.app = self;
req.res = res;
res.req = req;
if (req.url.indexOf('?') > 0) {
var query = url.parse(req.url).query;
req.params.get = queryString.parse(query);
}
next();
});
this.use('/', router(function(app){
self.routes = app;
}));
};
|
Inherit from connect.Server .
|
sys.inherits(Server, connect.Server);
|
Start listening on the given port / host .
param: Number port param: String host api: public
|
Server.prototype.listen = function(port, host){
this.set('env', process.env.EXPRESS_ENV || process.connectEnv.name);
this.runConfig('any', this.set('env'));
if (this.set('reload views')) {
view.watcher.call(this, this.set('reload views'));
}
connect.Server.prototype.listen.call(this, port, host);
};
|
Assign a custom exception handler callback fn .
|
Server.prototype.error = function(fn){
this.use('/', function(err, req, res, next){
fn.apply(this, arguments);
});
return this;
};
|
Assign setting to val , or return setting 's value.
|
Server.prototype.set = function(setting, val){
if (val === undefined) {
return this.settings[setting];
} else {
this.settings[setting] = val;
return this;
}
};
|
Enable setting .
|
Server.prototype.enable = function(setting){
return this.set(setting, true);
};
|
Disable setting .
|
Server.prototype.disable = function(setting){
return this.set(setting, false);
};
|
Redirect key to url .
|
Server.prototype.redirect = function(key, url){
this.redirects[key] = url;
return this;
};
|
Disable setting .
|
Server.prototype.configure = function(env, fn){
if (typeof env === 'function') fn = env, env = 'any';
(this.config[env] = this.config[env] || []).push(fn);
return this;
};
(function(method){
Server.prototype[method] = function(path, fn){
this.routes[method](path, fn);
return this;
};
return arguments.callee;
})('get')('post')('put')('del');
|
| lib/express/utils.js |
Parse mini markdown implementation.
The following conversions are supported,
primarily for the "flash" middleware:
foo or foo become <em>foo</em>
foo or foo become <strong>foo</strong>
A becomes <a href="B">A</a>
param: String str return: String api: public
|
exports.miniMarkdown = function(str){
return String(str)
.replace(/(__|\*\*)(.*?)\1/g, '<strong>$2</strong>')
.replace(/(_|\*)(.*?)\1/g, '<em>$2</em>')
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
};
|
Escape special characters in the given string of html.
param: String html return: String api: public
|
exports.htmlEscape = function(html) {
return String(html)
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>');
};
|
| lib/express/view.js |
Module dependencies.
|
var extname = require('path').extname,
mime = require('connect/utils').mime,
utils = require('connect/utils'),
http = require('http'),
sys = require('sys'),
fs = require('fs');
|
Cache supported template engine exports to
increase performance by lowering the number
of calls to require() .
|
var cache = {};
|
Cache view contents to prevent I/O hits.
|
var viewCache = {};
|
Clear the view cache.
|
exports.clearCache = function(){
viewCache = {};
};
|
View helpers merged with each render's locals.
|
var helpers = exports.helpers = {};
|
Render view partial with the given options .
Options
as Variable name for each collection value, defaults to the view name.
collection Array of objects, the name is derived from the view name itself.
For example video.html will have a object video available to it.
|
http.ServerResponse.prototype.partial = function(view, options, ext){
if (ext && view.indexOf('.') < 0) {
view += ext;
}
if (options instanceof Array) {
options = { collection: options };
}
options = options || {};
options.partial = true;
options.layout = false;
var collection = options.collection;
if (collection) {
var name = options.as || view.split('.')[0],
len = collection.length;
var locals = options.locals = options.locals || {};
locals.collectionLength = len;
return collection.map(function(val, i){
if (typeof name === 'string') {
locals[name] = val;
} else if (name === global) {
utils.merge(locals, val);
} else {
options.context = val;
}
locals.firstInCollection = i === 0;
locals.indexInCollection = i;
locals.lastInCollection = i === len - 1;
return this.render(view, options);
}, this).join('');
} else {
return this.render(view, options);
}
};
|
Render view with the given options and optional callback fn .
When a callback function is given a response will not be made
automatically, however otherwise a response of 200 and text/html is given.
Options
Most engines accept one or more of the following options,
both haml and jade accept all:
context Template evaluation context (this )locals Object containing local variablesfilename Filename used for the cache optioncache Cache intermediate JavaScript in memorydebug Output debugging information
param: String view param: Object options param: Function fn api: public
|
http.ServerResponse.prototype.render = function(view, options, fn){
options = options || {};
var defaultEngine = this.app.set('view engine');
if (view.indexOf('.') < 0 && defaultEngine) {
view += '.' + defaultEngine;
}
var self = this,
root = viewRoot(this.app),
ext = extname(view),
partial = options.partial,
layout = options.layout === undefined ? true : options.layout,
layout = layout === true
? 'layout' + ext
: layout;
if (this.app.set('env') === 'production') {
options.cache = true;
}
if (options.partial) {
root += '/partials';
}
var path = root + '/' + view;
function send(str) {
self.writeHead(200, {
'Content-Type': 'text/html',
'Content-Length': str.length
});
self.end(str);
}
options.locals = options.locals || {};
options.locals.__filename = options.filename = path;
options.locals.partial = function(view, options){
return self.partial.call(self, view, options, ext);
};
options.locals.__proto__ = helpers;
function error(err) {
if (fn) {
fn(err);
} else {
throw err;
}
}
try {
var str = viewCache[path] || cacheView(path);
} catch (err) {
return error(err);
}
var engine = cache[ext] || (cache[ext] = require(ext.substr(1)));
try {
var str = engine.render(str, options);
} catch (err) {
return error(err);
}
if (layout) {
options.layout = false;
options.locals.body = str;
self.render(layout, options);
} else if (partial) {
return str;
} else if (fn) {
fn(null, str);
} else {
send(str);
}
};
|