Created
October 4, 2012 06:31
-
-
Save craigyk/3831786 to your computer and use it in GitHub Desktop.
connect-session implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
crypto = require 'crypto' | |
connectionSecure = (req,trust_proxy=true) -> | |
secure_proxy = ( req.headers['x-forwarded-proto'] or '' ).toLowerCase() == 'https' | |
req.connection.encrypted or ( trust_proxy and secure_proxy ) | |
createID = (len) -> crypto.randomBytes(Math.ceil(len*3/4)).toString('base64').slice(0,len) | |
# not implemented yet | |
signId = (unsignedid,secret) -> unsignedid | |
unsignId = (signedid,secret) -> signedid | |
expiresAfter = (age) -> | |
if age? | |
new Date Date.now() + age | |
else null | |
class MemoryStore | |
constructor : -> | |
@store = {} | |
get : (sid,next) -> | |
# maybe I should move all these to nextTick? | |
# just in case someone expects them to be asynchronous | |
next null, @store[sid] ? {} | |
set : (sid,session,next) -> | |
next null, @store[sid] = session | |
destroy : (sid,next) -> | |
next null, delete @store[sid] | |
this.session = (options) -> | |
secret = options.secret | |
store = options.store or new MemoryStore | |
key = options.key or 'sessionid' | |
if not secret | |
throw new Error 'a secret is required for sessions' | |
# well no, not yet, but soon | |
(req,res,next) -> | |
if req.session | |
return do next | |
if not req.cookies[key] or req.cookies[key] == 'undefined' | |
req.sessionid = createID 128 | |
else req.sessionid = unsignId req.cookies[key], secret | |
res.on 'header', -> | |
if not req.session then return | |
if req.cookies.expires == null | |
if req.cookies[key] == signId req.sessionid, secret | |
return console.log "not resending session id cookie" | |
if req.cookies.secure | |
if not connectionSecure req, options.trust_proxy | |
return console.log "skipped setting session, non-secure connection with secure cookie" | |
# co-opt cookies to keep them all server-side? | |
req.session.cookies = req.cookies | |
res.cookie key, ( signId req.sessionid, secret ), | |
httpOnly : options.httpOnly ? true | |
secure : options.secure ? false | |
expires : expiresAfter options.max_age | |
path : options.path ? '/' | |
end = res.end | |
res.end = (data, encoding) -> | |
res.end = end | |
if not req.session | |
return res.end data, encoding | |
store.set req.sessionid, req.session, (e) -> | |
res.end data, encoding | |
do req.pause | |
store.get req.sessionid, (err,session) -> | |
req.session = session or {} | |
req.cookies = req.session.cookies or {} | |
do req.resume # <- is order important here? | |
next err # |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment