lsm/micromono

View on GitHub
lib/web/middleware/layout.js

Summary

Maintainability
D
2 days
Test Coverage
/**
 * Module dependencies
 */

var assign = require('lodash.assign')

/**
 * The remote partial composing middleware
 */
module.exports = function(app) {
  var layoutName = app.get('micromono layout name') || 'layout'
  app.set('micromono layout name', layoutName)

  return function renderLayout(req, res, next) {
    if (req.__micromono_layout_attached__) {
      next()
      return
    }
    req.__micromono_layout_attached__ = true

    var _end = res.end
    var _write = res.write
    var _writeHead = res.writeHead

    var _headers
    res.writeHead = function(code, message, headers) {
      if (code)
        res.statusCode = code

      switch (typeof message) {
        case 'string':
          res.statusMessage = message
          break
        default:
        case 'object':
          _headers = headers
      }

      return res
    }

    function end(data, encoding, callback) {
      res.set('Content-Length', Buffer.byteLength(data, encoding))
      if (!res._header)
        res._implicitHeader()
      _writeHead.call(res, res.statusCode)
      if (data)
        _write.call(res, data, encoding)
      _end.call(res, callback)
    }

    var buf = ''

    res.write = function(body) {
      buf += body
      return true
    }

    res.end = function(data, encoding, callback) {
      if (data) {
        if ('function' === typeof data)
          callback = data
        else
          buf += data
      }

      if (_headers)
        res.set(_headers)

      var locals
      var JSONStr
      var contentType = res.getHeader('content-type')

      if (/json/.test(contentType)) {
        JSONStr = buf.toString('utf8')
      } else if (/text/.test(contentType)) {
        locals = {
          yield: buf
        }
      } else {
        // No content type, just return what we get
        end(buf, encoding, callback)
        return
      }

      var accept = req.accepts(['html', 'json'])

      if (JSONStr) {
        try {
          locals = JSON.parse(JSONStr)
        } catch (e) {
          res.status(500)
          end('Service error.', 'utf8')
          return
        }
      }

      // merge local context
      res.locals = assign(res.locals, locals)

      if (req.xhr && 'json' === accept) {
        // send json if this is a xhr request which accepts json
        res.type('json')
        var jsonStr = JSON.stringify(locals)
        end(jsonStr, encoding, callback)
      } else if ('html' === accept) {
        // render html page with data
        res.type('html')
        app.render(layoutName, res.locals, function(err, html) {
          if (err) {
            var data = err.toString()
            res.status(500)
            res.statusMessage = 'Server error.'
            end(data, 'utf8')
            return
          }
          end(html, encoding, callback)
        })
      } else {
        res.status(406)
        end('Not Acceptable.', 'utf8')
      }
    }

    next()
  }
}