ConnectHigh performance middleware for node. | |
| 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();
}
}
};
|
| 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();
};
};
|
| 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();
};
};
|
| 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){
require.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 cssless 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();
};
};
|
| 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();
};
};
|
| 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) {
try {
req.cookies = utils.parseCookie(cookie);
delete req.headers.cookie;
} catch (err) {
}
next();
} else {
next();
}
};
};
|
| 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);
}
};
};
|
| lib/connect/middleware/gzip-compress.js |
Module dependencies.
|
var child_process = require('child_process'),
sys = require('sys'),
compress = require('compress');
|
Provides gzip compression via the node-compress library.
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)
&& headers["Content-Encoding"] === undefined)) {
res.writeHead = writeHead;
res.writeHead(code, headers);
return;
}
headers["Content-Encoding"] = "gzip";
delete headers["Content-Length"];
var gzip = new compress.GzipStream();
res.write = function (chunk, encoding) {
gzip.setInputEncoding(encoding);
gzip.write(chunk);
};
res.end = function (chunk, encoding) {
if (chunk) {
res.write(chunk, encoding);
}
gzip.close();
};
gzip.addListener('data', function (chunk) {
write.call(res, chunk);
});
gzip.addListener('error', function(err) {
res.write = write;
res.end = end;
next(err);
});
gzip.addListener('end', function (code) {
res.write = write;
res.end = end;
res.end();
});
res.writeHead = writeHead;
res.writeHead(code, headers);
};
next();
};
};
|
| lib/connect/middleware/gzip-proc.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)
&& headers["Content-Encoding"] === undefined)) {
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();
};
};
|
| lib/connect/middleware/gzip.js |
try {
module.exports = require('./gzip-compress');
} catch (e) {
if (/^Cannot find module /.test(e.message))
module.exports = require('./gzip-proc');
else
throw e;
}
|
|
| 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.
|
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();
}
};
};
|
| 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();
}
};
|
| lib/connect/middleware/logger.js |
Log requests with the given options .
Options
format Format string, see below for tokensstream 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();
};
};
|
| 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) {
var method = req.method;
if (typeof req.body === 'object' && key in req.body) {
method = req.body[key];
delete req.body[key];
} else if (req.headers['x-http-method-override']) {
method = req.headers['x-http-method-override'];
}
method = method.toUpperCase();
if (methods.indexOf(method) >= 0) {
req.method = method;
}
next();
};
};
|
| 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();
}
};
|
| 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();
};
};
|
| 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 route,
self = this;
(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();
}
})();
};
}
|
| 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);
|
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();
};
|
Destroy the session associated with the given hash .
param: String hash api: public
|
MemoryStore.prototype.destroy = function(hash, fn){
delete this.sessions[hash];
fn && fn();
};
|
Invoke the given callback fn with all active sessions.
param: Function fn api: public
|
MemoryStore.prototype.all = function(fn){
var arr = [],
keys = Object.keys(this.sessions);
for (var i = 0, len = keys.length; i < len; ++i) {
arr.push(this.sessions[keys[i]]);
}
fn(null, arr);
};
|
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);
};
|
| 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
|
Session.prototype.regenerate = function(fn){
this.req.sessionStore.regenerate(this.req, fn);
};
|
| lib/connect/middleware/session/store.js |
Module dependencies.
|
var Session = require('./session'),
utils = require('./../../utils');
|
Destroy session associated with the given hash
by passing null to Store#get() .
param: String hash param: Function fn api: public
|
Store.prototype.destroy = function(hash, fn){
this.set(hash, null, fn);
};
|
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);
});
};
|
| lib/connect/middleware/session.js |
Module dependencies.
|
var MemoryStore = require('./session/memory'),
Session = require('./session/session'),
utils = require('./../utils');
|
Setup session store with the given options .
Options
store Session store instancefingerprint 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();
}
}
};
|
| 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 maxAge of one hour.
|
var maxAge = 1000 * 60 * 60;
|
Static file server.
Options
root Root path from which to serve static files.
param: String root return: Function api: public
|
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);
}
});
};
};
|
| 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();
}
};
};
|