ConnectHigh performance middleware for node. | |
bodyDecoder | lib/connect/middleware/bodyDecoder.js |
Module dependencies.
|
var queryString = require('querystring');
|
Supported decoders.
- application/x-www-form-urlencoded
- application/json
|
exports.decode = {
'application/x-www-form-urlencoded': queryString.parse,
'application/json': JSON.parse
};
|
Decode request bodies.
return: Function
api: public
|
module.exports = function bodyDecoder(){
return function bodyDecoder(req, res, next) {
var decoder = exports.decode[mime(req)];
if (decoder) {
var data = '';
req.setEncoding('utf8');
req.addListener('data', function(chunk) { data += chunk; });
req.addListener('end', function() {
req.rawBody = data;
try {
req.body = data
? decoder(data)
: {};
} catch (err) {
return next(err);
}
next();
});
} else {
next();
}
}
};
|
cache | lib/connect/middleware/cache.js |
Module dependencies.
|
var Buffer = require('buffer').Buffer;
|
Cache in memory for the given cacheDuration .
|
module.exports = function cache(cacheDuration){
var cache = {},
queue = {};
return function cache(req, res, next) {
if (req.method !== "GET") {
next();
return;
}
var key = req.headers["accept-encoding"] + req.url,
writeHead = res.writeHead,
write = res.write,
end = res.end,
code,
headers,
chunks = [],
totalSize = 0;
function serve() {
var resp = cache[key];
var headers = resp.headers;
headers["Date"] = (new Date).toUTCString();
headers["Content-Length"] = resp.body.length;
if (localQueue) {
for (var i = 0, l = localQueue.length; i < l; i++) {
var localRes = localQueue[i];
localRes.writeHead(resp.code, headers);
localRes.end(resp.body);
}
delete queue[key];
} else {
res.writeHead(resp.code, headers);
res.end(resp.body);
}
}
if (cache[key]) {
serve();
return;
}
var localQueue = queue[key];
if (localQueue) {
localQueue[localQueue.length] = res;
return;
}
localQueue = queue[key] = [res];
res.writeHead = function (setCode, setHeaders) {
code = setCode;
headers = setHeaders;
};
res.write = function (chunk, encoding) {
if (typeof chunk === 'string') {
var length;
if (!encoding || encoding === 'utf8') {
length = Buffer.byteLength(chunk);
}
var buffer = new Buffer(length);
buffer.write(chunk, encoding);
chunks.push(buffer);
} else {
chunks.push(chunk);
}
totalSize += chunk.length;
};
res.end = function (chunk, encoding) {
if (chunk) {
res.write(chunk, encoding);
}
var body = new Buffer(totalSize);
var offset = 0;
chunks.forEach(function (chunk) {
chunk.copy(body, offset);
offset += chunk.length;
});
cache[key] = {
body: body,
code: code,
headers: headers
};
res.writeHead = writeHead;
res.write = write;
res.end = end;
serve();
if (cacheDuration) {
setTimeout(function(){
delete cache[key];
}, cacheDuration);
} else {
delete cache[key];
}
};
next();
};
};
|
cacheManifest | lib/connect/middleware/cacheManifest.js |
Module dependencies.
|
var fs = require('fs'),
Utils = require('../utils'),
Url = require('url'),
Path = require('path');
|
Generate cache manifest for the given root , networks ,
and fallbacks .
param: String root
param: Array networks
param: Array fallbacks
return: Function
api: public
|
module.exports = function cacheManifest(root, networks, fallbacks) {
root = root || process.cwd();
var suffix = "";
if (networks) {
suffix += "\n\nNETWORK:\n" + networks.join("\n");
}
if (fallbacks) {
suffix += "\n\nFALLBACK:\n" +
fallbacks.map(function (second, first) {
return first + " " + second;
}).join("\n");
}
return function cacheManifest(req, res, next) {
if (Url.parse(req.url).pathname === "/cache.manifest") {
Utils.find(root, (/./), function (err, files) {
var latestMtime = 0;
files = files.map(function (entry) {
if (entry.mtime > latestMtime) {
latestMtime = entry.mtime;
}
return entry.path.substr(1);
});
var manifest = "CACHE MANIFEST\n"
+ "# " + latestMtime.toUTCString() + "\n"
+ files.join("\n")
+ suffix;
res.writeHead(200, {
"Content-Type": "text/cache-manifest",
"Last-Modified": latestMtime.toUTCString(),
"Content-Length": manifest.length
});
res.end(manifest);
});
return;
}
next();
};
};
|
compiler | lib/connect/middleware/compiler.js |
Module dependencies.
|
var fs = require('fs'),
path = require('path');
|
Bundled compilers:
|
var compilers = exports.compilers = {
sass: {
match: /\.css$/,
ext: '.sass',
compile: function(str, fn){
require.async('sass', function(err, sass){
if (err) {
fn(err);
} else {
try {
fn(null, sass.render(str));
} catch (err) {
fn(err);
}
}
});
}
},
less: {
match: /\.css$/,
ext: '.less',
compile: function(str, fn){
render.async('less', function(err, less){
if (err) {
fn(err);
} else {
try {
less.render(str, fn);
} catch (err) {
fn(err);
}
}
});
}
}
};
|
Setup compiler.
Options
src Source directory, defaults to CWD.
dest Destination directory, defaults src .
enable Array of enabled compilers.
Compilers
sass Compiles cass to css
less Compiles less to css
param: Object options
api: public
|
module.exports = function compiler(options){
options = options || {};
var srcDir = process.connectEnv.compilerSrc || options.src || process.cwd(),
destDir = process.connectEnv.compilerDest || options.dest || srcDir,
enable = options.enable;
if (!enable || enable.length === 0) {
throw new Error(s "enable" option is not set, nothing will be compiled.');
}
return function compiler(req, res, next){
for (var i = 0, len = enable.length; i < len; ++i) {
var name = enable[i],
compiler = compilers[name];
if (compiler.match.test(req.url)) {
var src = (srcDir + req.url).replace(compiler.match, compiler.ext),
dest = destDir + req.url;
fs.stat(src, function(err, srcStats){
if (err) {
if (err.errno === process.ENOENT) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
} else {
next(err);
}
} else {
fs.stat(dest, function(err, destStats){
if (err) {
if (err.errno === process.ENOENT) {
compile();
} else {
next(err);
}
} else {
if (srcStats.mtime > destStats.mtime) {
compile();
} else {
next();
}
}
})
}
});
function compile() {
fs.readFile(src, 'utf8', function(err, str){
if (err) {
next(err);
} else {
compiler.compile(str, function(err, str){
if (err) {
next(err);
} else {
fs.writeFile(dest, str, 'utf8', function(err){
next(err);
});
}
});
}
});
}
return;
}
}
next();
};
};
|
conditionalGet | lib/connect/middleware/conditionalGet.js |
Conditional GET request support.
return: Function
api: public
|
module.exports = function conditionalGet(){
return function conditionalGet(req, res, next) {
if (!(req.method === "GET" &&
(req.headers["if-modified-since"] || req.headers["if-none-match"])
)) {
next();
return;
}
var since = req.headers["if-modified-since"],
oldEtag = req.headers["if-none-match"],
writeHead = res.writeHead,
write = res.write,
end = res.end;
since = since && Date.parse(since).valueOf();
res.writeHead = function (code, headers) {
var lastModified = headers["Last-Modified"],
etag = headers["Etag"];
lastModified = lastModified && Date.parse(lastModified).valueOf();
if (!(code === 200 &&
(lastModified === since || oldEtag === etag)
)) {
res.writeHead = writeHead;
res.writeHead(code, headers);
return;
}
res.write = function () {};
res.end = function () {
res.writeHead = writeHead;
res.write = write;
res.end = end;
var newHeaders = {};
headers.forEach(function (value, key) {
if (key.indexOf("Content") < 0) {
newHeaders[key] = value;
}
});
res.writeHead(304, newHeaders);
res.end();
};
};
next();
};
};
|
cookieDecoder | lib/connect/middleware/cookieDecoder.js |
Module dependencies.
|
var utils = require('./../utils');
|
Parse Cookie header and populate req.cookies .
return: Function
api: public
|
module.exports = function cookieDecoder(){
return function cookieDecoder(req, res, next) {
var cookie = req.headers.cookie;
req.cookies = {};
if (cookie) {
process.nextTick(function(){
try {
req.cookies = utils.parseCookie(cookie);
delete req.headers.cookie;
} catch (err) {
}
next();
});
} else {
next();
}
};
};
|
errorHandler | lib/connect/middleware/errorHandler.js |
Module dependencies.
|
var utils = require('./../utils'),
sys = require('sys'),
fs = require('fs');
|
Setup error handler with the given options .
Options
showStack respond with both the error message and stack trace. Defaults to false
showMessage respond with the exception message only. Defaults to false
dumpExceptions dump exceptions to stderr (without terminating the process). Defaults to false
param: Object options
return: Function
api: public
|
module.exports = function errorHandler(options){
options = options || {};
var showStack = options.showStack,
showMessage = options.showMessage,
dumpExceptions = options.dumpExceptions;
if (process.connectEnv.showErrorStack !== undefined) {
showStack = op = utils.toBoolean(process.connectEnv.showErrorStack);
}
if (process.connectEnv.showErrorMessage !== undefined) {
showMessage = utils.toBoolean(process.connectEnv.showErrorMessage);
}
if (process.connectEnv.dumpExceptions !== undefined) {
dumpExceptions = utils.toBoolean(process.connectEnv.dumpExceptions);
}
return function errorHandler(err, req, res, next){
if (dumpExceptions) {
sys.error(err.stack);
}
if (showStack) {
var accept = req.headers.accept || '';
if (accept.indexOf('html') !== -1) {
fs.readFile(__dirname + '/../public/style.css', function(e, style){
style = style.toString('ascii');
fs.readFile(__dirname + '/../public/error.html', function(e, html){
var stack = err.stack
.split('\n').slice(1)
.map(function(v){ return '<li>' + v + '</li>'; }).join('');
html = html
.toString('utf8')
.replace('{style}', style)
.replace('{stack}', stack)
.replace(/\{error\}/g, err.toString());
res.writeHead(500, { 'Content-Type': 'text/html' });
res.end(html);
});
});
} else if (accept.indexOf('json') !== -1) {
var json = JSON.stringify({ error: err });
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(json);
} else {
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(err.stack);
}
} else {
var body = showMessage
? err.toString()
: 'Internal Server Error';
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end(body);
}
};
};
|
flash | lib/connect/middleware/flash.js |
Module dependencies.
|
var utils = require('./../utils');
|
Provide req.flash() .
return: Function
api: public
|
module.exports = function flash(){
return function flash(req, res, next) {
|
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: [] }
|
req.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;
}
};
next();
};
};
|
| lib/connect/middleware/format.js |
Module dependencies.
|
var connect = require('./../index'),
sys = require('sys');
|
Extract url “formats” aka extensions from the request
url, and assigns req.format .
Examples
// curl http://localhost:3000/users.json
handle: function(req, res, next){
switch (req.format) {
case 'json':
sys.puts(req.url);
// => "users"
// respond with json
break;
default:
// respond with your default format
}
}
return: Function
api: public
|
module.exports = function format(){
return function format(req, res, next) {
if (/\.(\w+)($|#|\?)/.exec(req.url)) {
req.format = RegExp.$1;
req.url = req.url.replace('.' + req.format, '');
}
next();
};
};
|
gzip | lib/connect/middleware/gzip.js |
Module dependencies.
|
var child_process = require('child_process'),
sys = require('sys');
|
Provides gzip compression via the gzip executable.
return: Function
api: public
|
module.exports = function gzip(){
return function gzip(req, res, next) {
var writeHead = res.writeHead,
write = res.write,
end = res.end;
res.writeHead = function (code, headers) {
var type = headers["Content-Type"],
accept = req.headers["accept-encoding"];
if (!(code === 200 && accept && accept.indexOf('gzip') >= 0
&& type && (/(text|javascript|json)/).test(type))) {
res.writeHead = writeHead;
res.writeHead(code, headers);
return;
}
headers["Content-Encoding"] = "gzip";
delete headers["Content-Length"];
var gzip = child_process.spawn("gzip", ["-9"]);
res.write = function (chunk, encoding) {
gzip.stdin.write(chunk, encoding);
};
res.end = function (chunk, encoding) {
if (chunk) {
res.write(chunk, encoding);
}
gzip.stdin.end();
};
gzip.stdout.addListener('data', function (chunk) {
write.call(res, chunk);
});
gzip.addListener("exit", function (code) {
res.write = write;
res.end = end;
res.end();
});
res.writeHead = writeHead;
res.writeHead(code, headers);
};
next();
};
};
|
jsonrpc | lib/connect/middleware/jsonrpc.js |
Module dependencies.
|
var sys = require('sys'),
parse = require('url').parse,
Buffer = require('buffer').Buffer,
http = require('http');
|
Export the setup() function.
|
exports = module.exports = jsonrpc;
|
JSON-RPC version.
|
var VERSION = exports.VERSION = '2.0';
|
JSON parse error.
|
var PARSE_ERROR = exports.PARSE_ERROR = -32700;
|
Invalid request due to invalid or missing properties.
|
var INVALID_REQUEST = exports.INVALID_REQUEST = -32600;
|
Service method does not exist. missing pro
|
var METHOD_NOT_FOUND = exports.METHOD_NOT_FOUND = -32601;
|
Invalid parameters.
|
var INVALID_PARAMS = exports.INVALID_PARAMS = -32602;
|
Internal JSON-RPC error.
|
var INTERNAL_ERROR = exports.INTERNAL_ERROR = -32603;
|
Default error messages.
|
var errorMessages = exports.errorMessages = {};
errorMessages[PARSE_ERROR] = 'Parse Error.';
errorMessages[INVALID_REQUEST] = 'Invalid Request.';
errorMessages[METHOD_NOT_FOUND] = 'Method Not Found.';
errorMessages[INVALID_PARAMS] = 'Invalid Params.';
errorMessages[INTERNAL_ERROR] = 'Internal Error.';
|
Accepts any number of objects, exposing their methods.
param: Object …
return: Function
api: public
|
function jsonrpc(services) {
services = services || {};
for (var i = 0, len = arguments.length; i < len; ++i) {
arguments[i].forEach(function(val, key){
services[key] = val;
});
}
|
Handle JSON-RPC request.
param: Object rpc
param: Function respond
>
|
function handleRequest(rpc, respond){
if (validRequest(rpc)) {
var method = services[rpc.method];
if (typeof method === 'function') {
var params = [];
if (rpc.params instanceof Array) {
params = rpc.params;
} else if (typeof rpc.params === 'object') {
var names = method.toString().match(/\((.*?)\)/)[1].match(/[\w]+/g);
if (names) {
for (var i = 0, len = names.length; i < len; ++i) {
params.push(rpc.params[names[i]]);
}
} else {
return respond({ error: { code: INVALID_PARAMS, message: 'This service does not support named parameters.' }});
}
}
function reply(err, result){
if (err) {
if (typeof err === 'number') {
respond({
error: {
code: err
}
});
} else {
respond({
error: {
code: err.code || INTERNAL_ERROR,
message: err.message
}
});
}
} else {
respond({
result: result
});
}
}
method.apply(reply, params);
} else {
respond({ error: { code: METHOD_NOT_FOUND }});
}
} else {
respond({ error: { code: INVALID_REQUEST }});
}
}
return function jsonrpc(req, res, next) {
var me = this,
contentType = req.headers['content-type'] || '';
if (req.method === 'POST' && contentType.indexOf('application/json') >= 0) {
var data = '';
req.setEncoding('utf8');
req.addListener('data', function(chunk) { data += chunk; });
req.addListener('end', function() {
try {
var rpc = JSON.parse(data),
batch = rpc instanceof Array;
} catch (err) {
return respond(normalize(rpc, { error: { code: PARSE_ERROR }}));
}
|
Normalize response object.
|
function normalize(rpc, obj) {
obj.id = rpc && typeof rpc.id === 'number'
? rpc.id
: null;
obj.jsonrpc = VERSION;
if (obj.error && !obj.error.message) {
obj.error.message = errorMessages[obj.error.code];
}
return obj;
}
|
Respond with the given response object.
|
function respond(obj) {
var body = JSON.stringify(obj);
res.writeHead(200, {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(body)
});
res.end(body);
}
if (batch) {
var responses = [],
len = rpc.length,
pending = len;
for (var i = 0; i < len; ++i) {
(function(rpc){
handleRequest.call(me, rpc, function(obj){
responses.push(normalize(rpc, obj));
if (!--pending) {
respond(responses);
}
});
})(rpc[i]);
}
} else {
handleRequest.call(me, rpc, function(obj){
respond(normalize(rpc, obj));
});
}
});
} else {
next();
}
};
};
|
lint | lib/connect/middleware/lint.js |
Module dependencies.
|
var connect = require('./../index'),
sys = require('sys');
|
Setup lint for the given server .
return: Function
api: public
|
module.exports = function lint(server){
if (!server) {
throw new Error('lint "server" must be passed.');
}
if (process.connectEnv.name !== 'development') {
warn('"lint" middleware should never be enabled outside of the development environment');
}
checkStack(server.stack);
return function(req, res, next){
next();
}
};
|
logger | lib/connect/middleware/logger.js |
Log requests with the given options .
Options
format Format string, see below for tokens
stream Output stream, defaults to stdout
Tokens
:req[header] ex: :req[Accept]
:res[header] ex: :res[Content-Length]
:http-version
:response-time
:remote-addr
:date
:method
:url
:referrer
:user-agent
:status
return: Function
api: public
|
module.exports = function logger(options) {
options = options || {};
var fmt = process.connectEnv.logFormat || options.format,
stream = options.stream || process.stdout;
return function logger(req, res, next) {
var start = +new Date,
statusCode,
resHeaders,
writeHead = res.writeHead,
end = res.end,
url = req.url;
res.writeHead = function(code, headers){
res.writeHead = writeHead;
res.writeHead(code, headers);
res.statusCode = statusCode = code;
res.headers = resHeaders = headers;
};
if (fmt) {
res.end = function(chunk, encoding) {
res.end = end;
res.end(chunk, encoding);
res.responseTime = +new Date - start;
stream.write(format(fmt, req, res) + '\n', 'ascii');
};
} else {
res.end = function(chunk, encoding) {
res.end = end;
res.end(chunk, encoding);
stream.write((req.socket && req.socket.remoteAddress)
+ ' - - [' + (new Date).toUTCString() + ']'
+ ' "' + req.method + ' ' + url
+ ' HTTP/' + req.httpVersionMajor + '.' + req.httpVersionMinor + '" '
+ statusCode + ' ' + (resHeaders['Content-Length'] || '-')
+ ' "' + (req.headers['referer'] || req.headers['referrer'] || '')
+ '" "' + (req.headers['user-agent'] || '') + '"\n', 'ascii');
};
}
next();
};
};
|
methodOverride | lib/connect/middleware/methodOverride.js |
Module dependencies.
|
var queryString = require('querystring');
|
Valid http methods.
|
var methods = ['GET', 'POST', 'PUT', 'HEAD', 'DELETE', 'OPTIONS'];
|
Pass an optional key to use when checking for
a method override, othewise defaults to _method.
param: String key
return: Function
api: public
|
module.exports = function methodOverride(key){
key = key || "_method";
return function methodOverride(req, res, next) {
if (typeof req.body === 'object' && key in req.body) {
var method = req.body[key].toUpperCase();
if (methods.indexOf(method) >= 0) {
req.method = method;
delete req.body[key];
}
}
next();
};
};
|
pubsub | lib/connect/middleware/pubsub.js |
Module dependencies.
|
var sys = require('sys');
|
Subscriber cache.
|
var cache = {};
|
redirect | lib/connect/middleware/redirect.js |
Module dependencies.
|
var connect = require('./../index'),
sys = require('sys');
|
Provide res.redirect() .
Examples
// Absolute
res.redirect('http://google.com');
// Relative + custom status
res.redirect('/foo', 301);
// Referr?er
res.redirect('back');
return: Function
api: public
|
module.exports = function redirect(){
return function redirect(req, res, next) {
var map = {
back: req.headers.referrer || req.headers.referer || '/'
};
res.redirect = function(url, code){
this.writeHead(code || 302, {
'Location': map[url] || url
});
this.end();
};
next();
};
};
|
repl | lib/connect/middleware/repl.js |
Module dependencies.
|
var net = require('net'),
repl = require('repl');
|
Start a REPL on the given unix domain socket path.
Options
-
sockect Unix domain socket path. Defaults to “/tmp/connect.sock”
-
prompt REPL prompt string. Defaults to “node> ”
Example
$ rlwrap telnet /tmp/connect.sock
|
module.exports = function repl(prompt, socket){
prompt = process.connectEnv.replPrompt || prompt || 'node> ';
socket = process.connectEnv.replSocket || socket || '/tmp/connect.sock';
net.createServer(function (stream) {
repl.start(prompt, stream);
}).listen(socket);
return function repl(req, res, next){
next();
}
};
|
responseTime | lib/connect/middleware/responseTime.js |
Responds with the X-Response-Time header in milliseconds.
return: Function
api: public
|
module.exports = function responseTime(){
return function responseTime(req, res, next){
var start = new Date,
writeHead = res.writeHead;
res.writeHead = function(code, headers){
res.writeHead = writeHead;
headers['X-Response-Time'] = (new Date - start) + "ms";
res.writeHead(code, headers);
};
next();
};
};
|
router | lib/connect/middleware/router.js |
Module dependencies.
|
var parse = require('url').parse;
|
Provides Sinatra and Express like routing capabilities.
Examples
connect.router(function(app){
app.get('/user/:id', function(req, res, params){
// populates params.id
});
})
param: Function fn
return: Function
api: public
|
module.exports = function router(fn){
var routes;
if (fn) {
routes = {};
fn.call(this, {
post: method.call(this, 'post'),
get: method.call(this, 'get'),
put: method.call(this, 'put'),
del: method.call(this, 'del')
});
} else {
throw new Error('router provider requires a callback function');
}
function method(name) {
var self = this,
localRoutes = routes[name] = routes[name] || [];
return function(path, fn){
var keys = [];
path = path instanceof RegExp
? path
: normalizePath(path, keys);
localRoutes.push(fn, path, keys);
return self;
};
}
return function router(req, res, next){
var self = this;
process.nextTick(function(){
var route;
(function pass(i){
if (route = match(req, routes, i)) {
req.params = req.params || {};
req.params.path = route._params;
try {
route.call(self, req, res, route._params, function(err){
if (err) {
next(err);
} else {
pass(++route._index);
}
});
} catch (err) {
next(err);
}
} else {
next();
}
})();
});
};
}
|
memory | lib/connect/middleware/session/memory.js |
Module dependencies.
|
var sys = require('sys'),
Store = require('./store'),
utils = require('./../../utils'),
Session = require('./session');
|
Initialize MemoryStore with the given options.
param: Object options
api: public
|
var MemoryStore = module.exports = function MemoryStore(options) {
options = options || {};
Store.call(this, options);
this.sessions = {};
this.reapInterval = options.reapInterval || 600000;
if (this.reapInterval !== -1) {
setInterval(function(self){
self.reap(self.maxAge);
}, this.reapInterval, this);
}
};
sys.inherits(MemoryStore, Store);
|
Destroy session associated with the given hash .
param: String hash
param: Function fn
api: public
|
MemoryStore.prototype.destroy = function(hash, fn){
var destroyed = hash in this.sessions;
delete this.sessions[hash];
fn && fn(null, destroyed);
};
|
Attempt to fetch session by the given hash .
param: String hash
param: Function fn
api: public
|
MemoryStore.prototype.get = function(hash, fn){
if (hash in this.sessions) {
fn(null, this.sessions[hash]);
} else {
fn();
}
};
|
Commit the given sess object associated with the given hash .
param: String hash
param: Session sess
param: Function fn
api: public
|
MemoryStore.prototype.set = function(hash, sess, fn){
this.sessions[hash] = sess;
fn && fn();
};
|
Clear all sessions.
param: Function fn
api: public
|
MemoryStore.prototype.clear = function(fn){
this.sessions = {};
fn && fn();
};
|
Fetch number of sessions.
param: Function fn
api: public
|
MemoryStore.prototype.length = function(fn){
fn(null, Object.keys(this.sessions).length);
};
|
session | lib/connect/middleware/session/session.js |
Module dependencies.
|
var utils = require('./../../utils');
|
Update lastAccess timestamp.
|
Session.prototype.touch = function(){
this.lastAccess = +new Date;
};
|
Destroy this session.
param: Function fn
api: public
|
Session.prototype.destroy = function(fn){
delete this.req.session;
this.req.sessionStore.destroy(this.req.sessionHash, fn);
};
|
Regenerate this request’s session.
param: Function fn
api: public
/em
|
Session.prototype.regenerate = function(fn){
this.req.sessionStore.regenerate(this.req, fn);
};
|
store | lib/connect/middleware/session/store.js |
Module dependencies.
|
var Session = require('./session'),
utils = require('./../../utils');
|
Re-generate the given requests’s session.
|
Store.prototype.regenerate = function(req, fn){
var self = this;
this.destroy(req.sessionHash, function(err, destroyed){
req.session = new Session(req, utils.uid());
req.sessionHash = self.hash(req);
fn(err, destroyed);
});
};
|
session | lib/connect/middleware/session.js |
Module dependencies.
|
var MemoryStore = require('./session/memory').MemoryStore,
Session = require('./session/session'),
utils = require('./../utils');
|
Setup session store with the given options .
Options
store Session store instance
fingerprint Custom fingerprint hashing function
param: Object options
return: Function
api: public
|
module.exports = function session(options){
options = options || {};
var key = 'connect.sid';
store = options.store || new MemoryStore;
var hash = store.hash = options.fingerprint || function(req){
return utils.md5(req.session.id
+ req.socket.remoteAddress
+ (req.headers['user-agent'] || ''));
};
return function session(req, res, next){
req.sessionStore = store;
if (req.cookies) {
var writeHead = res.writeHead;
res.writeHead = function(status, headers){
headers = headers || {};
res.writeHead = writeHead;
store.set(req.sessionHash, req.session);
store.cookie.expires = new Date(+new Date() + store.maxAge);
headers['Set-Cookie'] = utils.serializeCookie(key, req.session.id, store.cookie);
return res.writeHead(status, headers);
};
function generate() {
req.session = new Session(req, utils.uid());
req.sessionHash = hash(req);
next();
}
if (req.cookies[key]) {
req.session = new Session(req, req.cookies[key]);
req.sessionHash = hash(req);
store.get(req.sessionHash, function(err, sess){
if (err) {
next(err);
} else if (sess) {
req.session = new Session(req, sess);
req.session.touch();
next();
} else {
generate();
}
});
} else {
generate();
}
} else {
next();
}
}
};
|
staticProvider | lib/connect/middleware/staticProvider.js |
Module dependencies.
|
var fs = require('fs'),
Url = require('url'),
Buffer = require('buffer').Buffer,
Path = require('path'),
queryString = require('querystring'),
utils = require('./../utils');
|
Browser cache lifetime of one hour.
|
var lifetime = 1000 * 60 * 60;
|
Static file server.
Options
root Root path from which to serve static files.
param: String root
return: Function
api: public
P
|
module.exports = function staticProvider(root){
root = process.connectEnv.staticRoot || root || process.cwd();
return function staticProvider(req, res, next) {
if (req.method !== "GET") {
next();
return;
}
var url = Url.parse(req.url);
var pathname = url.pathname.replace(/\.\.+/g, '.'),
filename = Path.join(root, queryString.unescape(pathname));
if (filename[filename.length - 1] === "/") {
filename += "index.html";
}
var events = [];
function onData() {
events.push(["data"].concat(toArray(arguments)));
}
function onEnd() {
events.push(["end"].concat(toArray(arguments)));
}
req.addListener("data", onData);
req.addListener("end", onEnd);
fs.stat(filename, function (err, stat) {
req.removeListener("data", onData);
req.removeListener("end", onEnd);
if (err) {
if (err.errno === process.ENOENT) {
next();
for (var i = 0, len = events.length; i < len; ++i) {
req.emit.apply(req, events[i]);
}
return;
}
next(err);
return;
}
function onRead(err, data) {
if (err) {
next(err);
return;
}
if (typeof data === 'string') {
var b = new Buffer(data.length);
b.write(data, "binary");
data = b;
}
if (data.length === 0) {
data = "";
}
res.writeHead(200, {
"Content-Type": utils.mime.type(filename),
"Content-Length": data.length,
"Last-Modified": stat.mtime.toUTCString(),
"Cache-Control": "public max-age=" + 31536000
});
res.end(data);
}
if (process.version < "0.1.95" && process.version > "0.1.100") {
fs.readFile(filename, "binary", onRead);
} else {
fs.readFile(filename, onRead);
}
});
};
};
|
vhost | lib/connect/middleware/vhost.js |
Setup vhost for the given hostname and server .
Examples
connect.createServer(
connect.vhost('foo.com',
connect.createServer(...middleware...)
),
connect.vhost('bar.com',
connect.createServer(...middleware...)
)
);
param: String hostname
param: Server server
return: Function
api: public
|
module.exports = function vhost(hostname, server){
if (!hostname) {
throw new Error('vhost hostname required');
}
if (!server) {
throw new Error('vhost server required');
}
return function vhost(req, res, next){
var host = req.headers.host.split(':')[0];
if (host === hostname) {
server.handle(req, res);
} else {
next();
}
};
};
|