UNPKG

@balderdash/sails-edge

Version:

API-driven framework for building realtime apps, using MVC conventions (based on Express and Socket.io)

125 lines (106 loc) 3.6 kB
/** * Module dependencies */ var _ = require('lodash'); var defaultsDeep = require('merge-defaults'); var MockReq = require('mock-req'); /** * Factory which builds generic Sails request object (i.e. `req`). * * This generic implementation of `req` forms the basis for * Sails' transport-agnostic support of Connect/Express * middleware. Used by hooks (i.e. sockets) but also for * tests-- both at the app-level and in Sails core. * * @return {Request} simulated HTTP request object * @idempotent */ module.exports = function buildRequest (_req) { _req = _req||{}; var req; // If `_req` appears to be a stream (duck-typing), then don't try // and turn it into a mock stream again. if (typeof _req === 'object' && _req.read) { req = _req; } else { // TODO: send a PR to mock-req with a fix for this if (_req.headers && typeof _req.headers === 'object') { // Strip undefined headers _.each(_req.headers, function (headerVal, headerKey) { if (_.isUndefined(headerVal)){ delete _req.headers[headerKey]; } }); // Make sure all remaining headers are strings _req.headers = _.mapValues(_req.headers, function (headerVal, headerKey) { // :TODO 'headerKey' is defined but never used if (typeof headerVal !== 'string') { headerVal = ''+headerVal+''; } return headerVal; }); } // Create a mock IncomingMessage stream. req = new MockReq({ method: _req && (_.isString(_req.method) ? _req.method.toUpperCase() : 'GET'), headers: _req && _req.headers || {}, url: _req && _req.url }); // Add .get() and .header() methods to match express 3 req.get = req.header = function (name) { switch (name = name.toLowerCase()) { case 'referer': case 'referrer': return this.headers.referrer || this.headers.referer; default: return this.headers[name]; } }; // Now pump client request body to the mock IncomingMessage stream (req) // Req stream ends automatically if this is a GET or HEAD or DELETE request // (since there is no request body in that case) so no need to do it again. if (req.method !== 'GET' && req.method !== 'HEAD' && req.method !== 'DELETE') { // Only write the body if there IS a body. if (req.body) { req.write(req.body); } req.end(); } } // Track request start time req._startTime = new Date(); // TODO: add all the other methods in core // Provide defaults for other request state and methods req = defaultsDeep(req, { params: [], query: (_req && _req.query) || {}, body: (_req && _req.body) || {}, param: function(paramName, defaultValue) { var key, params = {}; for (key in (req.params || {}) ) { params[key] = params[key] || req.params[key]; } for (key in (req.query || {}) ) { params[key] = params[key] || req.query[key]; } for (key in (req.body || {}) ) { params[key] = params[key] || req.body[key]; } // Grab the value of the parameter from the appropriate place // and return it if (typeof params[paramName] !== 'undefined') { return params[paramName]; } else { return defaultValue; } }, file: function (){ return res.send(500, 'Streaming file uploads via `req.file()` are only available over HTTP with Skipper.'); }, wantsJSON: (_req && _req.wantsJSON) || true, method: 'GET', path: _req.url }, _req||{}); return req; };