Blog Archives

Node Routes with Functional Programming

Today’s post is a little short and a little late as I’m pretty busy at work!

I’m going to do a quick functional programming example that I do in my routing of my application, now there probably is an easier way, but as allways programming is a process.

Here’s the code:

_boolHandle = (_f) -> (req, res) ->
  _testExists req.params.ticketID, res, -></pre>
    _f req, res, (err, results) -> if err then res.status(500).json err else res.status(200).json results or true '/api/ticket/:ticketID/metadata', _boolHandle (req, res, cb) -> $tickets.metadata req.params.ticketID, req.body, cb

This is essentially a post handler in express 4 that calls a function that returns a function to call a function to call a standard response!

If we break it down, when we register the handler, normally this would be written as follows: '/api/ticket/:ticketID/metadata', (req, res) -> res.status(200).json true

My first step was figuring out that every call I made to the $ticket object calls it’s callback with (err, result) and returned the results, so my code then looks like this: '/api/ticket/:ticketID/metadata', (req, res) -> $ticket.metadata req.params.ticketID, (err, result) -> if err then res.status(500).json err else res.status(200).json result

Because I’m lazy I decided I didn’t want to write out the callback every time, it’s always the same so why bother? So my first functional programming block was this:

_boolHandle = (_f) -> (req, res) ->
  _f req, res, (err, results) -> if err then res.status(500).json err else res.status(200).json results or true '/api/ticket/:ticketID/metadata', _boolHandle (req, res, cb) -> $tickets.metadata req.params.ticketID, cb

As you can see I abstracted out the response by creating a wrapper around it. The other part I have in the code is the function that tests whether the ticketID actually exists (_testExists), if it exists it calls the callback else it returns a “ticket not found” error.

I hope this explanation helps someone out, if you have a better way of doing this – I’m all ears!!

CRM Migration (Part 2)

Part One

Continuing on my series on gradual migration from Coldfusion to Node-js today I’ll be writing up about the authentication system that allows me to have one login that tells both node and coldfusion that the user is authenticated. (Sorry about all the &gt; showing up everywhere – Can’t figure out how to get rid of them)


Having worked my way through many iterations of this code, I’m going to start with a quick rundown of the process it took me to get to the end result.

  1. “I can just proxy through all requests to the CF Server, that sends the cookies as well.” Good points of this is that there’s a node module for that (isn’t there always!), bad point is that if you want to have node communicate with coldfusion as well, for example sockets that call logic on CF, you can’t use the cookie from the CF Server if it’s set up correctly to prevent cookie jacking. So this was a no go as essentially I ended up with 3 sessions, Browser to CF, Browser to Nodejs and Nodejs to CF, not good!!
  2. “OK, so if I write my own proxy code I can control the cookie right?”. Well, not quite though we’re getting there, again with the same origin restriction on cookies this didn’t work so well.
  3. “Right, so I have to have all communication with CF sent via node and not store the CF cookie on the browser.” This is about right!

How It’s Done

So if you remember last week there was a function and variable I said I’d explain this week, testCookie and req.session.proxyCookie? Well both of those are to do with my authentication solution.

We start off with the basic cookie and session setup for node:

@use cookieParser security.cookieSecret
 @use session
    httpOnly: true
    secure: false
    maxAge: 3600000 * 8 # hour in ms * 8 = 8 hours
  secret: security.cookieSecret
  store: sessionstore
  saveUninitialized: true
  resave: true

Here we’re using a couchbase memcached session store to store our cookies with some extra settings.

Next we have three functions for working with the Cookies these are:

parseCookie = (cookie) -&gt;
 _cookie = request.jar()
 if cookie? then _cookie.setCookie require('tough-cookie').Cookie.parse(_c), security.proxyAddress for _c in cookie
testProxyCookie = (session) -&gt;
   _foundCFID = false
   for key, cookie of parseCookie(session.proxyCookie)[security.proxyCookieDomain]['/']
     if key.toLowerCase() is 'cfid' and cookie.value then _foundCFID = true
     cookie.lastAccessed = new Date().toISOString()
   return _foundCFID
   return false
@testCookie = (req, resp, cb, isLogin=false) =&gt;
  if req.session? and (not testProxyCookie(req.session) or isLogin) and resp.headers and resp.headers['set-cookie']
    req.session.proxyCookie = request.jar()
    req.session.proxyCookie resp.headers['set-cookie']
    @getSessionCookie req, (sidCookie) -&gt;
    sessionstore.set sidCookie, req.session, cb
  else cb()

@getSessionCookie = (req, cb) -&gt;
  cookieParser(security.cookieSecret) req, {}, (parseErr) -&gt;
  if parseErr then return next new Error 'Error parsing cookies.'
  # Get the SID cookie
  EXPRESS_SID_KEY = 'connect.sid'
  cb (req.secureCookies and req.secureCookies[EXPRESS_SID_KEY]) or
     (req.signedCookies and req.signedCookies[EXPRESS_SID_KEY]) or
     (req.cookies and req.cookies[EXPRESS_SID_KEY]), sessionstore

@sessionAuth = (req, res, next) =&gt;
  @getSessionCookie req, (sidCookie) =&gt;
    req.sessionroomid = sidCookie
    if testProxyCookie req.session then next()
    else request
      uri: "#{security.proxyAddress}index.cfm/users/nodetestlogin.json"
      method: 'GET'
    , (err, resp, data) =&gt; @testCookie req, resp, next, true
@all '*', @sessionAuth

Let’s Break it Down!!

So, to start off when a user hits a page, the `@all ‘*’, @sessionAuth` gets hit. this in turn calls the `getSessionCookie` which if you haven’t guessed loads the cookies sent to node and finds the ‘connect.sid’ cookie value. We then store this cookie value in the request as the req.sessionroomid which we’ll use later for sockets and updating just one client across all his tabs (I think this may be a security hole but I’m yet to go back and review it yet). Then we call `testProxyCookie`, this function does two important things, first, it checks that the cookie we have stored in the session for communicating with CF is valid, and second it updates the lastAccessed value. Updating the lastAccessed value is important as when you send the cookie through CF uses this to detect if your session should have timed out yet or not! If you don’t update this and have say a 30 minute session timeout on CF, then even if you keep contacting CF constantly, 30 minutes after your first contact your session will expire!! Back in `sessionAuth` if the proxy cookie is valid (`testProxyCookie()` returns true) then we continue via `next()`, if not we send a request to the CF server using request and then use `@testCookie` to set the proxyCookie from the result.

In short `@testCookie` reads the response from the CF Server, parses the cookies and then saves the value in the session value, we later use that cookie with request to authenticate to the CF Server. Beyond the above you can setup your node.js server as you normally would and this will take care of all the integration.

Till Next Time (Which I am yet to decide what I’ll write about!).


I found a nasty bug that runs around the storage of tough-cookie objects – basically it doesn’t work! My solution was to store the ‘set-cookie’ headers instead and then add a ‘parseCookie’ method to convert it into the actual cookie jar object. This means that when you make the call to the CF server you do the following:

  uri: "#{security.proxyAddress}/index.cfm"
  method: 'GET'
  jar: parseCookie req.session.proxyCookie
, (err, resp, data) =&gt; #handle response here!