diff --git a/server/middleware/apiProxy.js b/server/middleware/apiProxy.js index 924578ab..12a2a249 100644 --- a/server/middleware/apiProxy.js +++ b/server/middleware/apiProxy.js @@ -13,20 +13,15 @@ var separator = '/-/'; module.exports = apiProxy; function apiProxy(dataAdapter) { - return function(req, res, next) { + var middleware = function(req, res, next) { var api; api = _.pick(req, 'query', 'method', 'body'); api.path = apiProxy.getApiPath(req.path); api.api = apiProxy.getApiName(req.path); - api.headers = { - 'x-forwarded-for': apiProxy.getXForwardedForHeader(req.headers, req.ip) - }; - dataAdapter.request(req, api, { - convertErrorCode: false - }, function(err, response, body) { + middleware.proxyRequest(req, res, api, { convertErrorCode: false }, function(err, response, body) { if (err) return next(err); // Pass through statusCode. @@ -34,6 +29,15 @@ function apiProxy(dataAdapter) { res.json(body); }); }; + + middleware.proxyRequest = function proxyRequest(req, res, api, options, callback) { + api.headers = api.headers || {}; + api.headers['x-forwarded-for'] = apiProxy.getXForwardedForHeader(req.headers, req.ip); + + dataAdapter.request(req, api, options, callback); + }; + + return middleware; }; apiProxy.getApiPath = function getApiPath(path) { diff --git a/server/middleware/initApp.js b/server/middleware/initApp.js index 89bf3354..c094265f 100644 --- a/server/middleware/initApp.js +++ b/server/middleware/initApp.js @@ -24,6 +24,7 @@ module.exports = function(appAttributes, options) { * This will only be accessible on the server. */ req: req, + res: res, entryPath: options.entryPath, modelUtils: options.modelUtils }; @@ -50,6 +51,10 @@ module.exports = function(appAttributes, options) { var app = new App(attributes, appOptions); + if (options.proxyRequest) { + app.proxyRequest = options.proxyRequest; + } + /** * Stash the app instance on the request so can be accessed in other middleware. */ diff --git a/server/server.js b/server/server.js index 2a42bb65..a47fdb49 100644 --- a/server/server.js +++ b/server/server.js @@ -80,27 +80,13 @@ function Server(options) { Server.prototype.configure = function(fn) { var dataAdapter = this.dataAdapter, apiPath = this.options.apiPath, - notApiRegExp = new RegExp('^(?!' + apiPath.replace('/', '\\/') + '\\/)'); + notApiRegExp = new RegExp('^(?!' + apiPath.replace('/', '\\/') + '\\/)'), + apiProxyMiddleware; - this._configured = true; + this.options.apiProxy = this.options.apiProxy || middleware.apiProxy; + apiProxyMiddleware = this.options.apiProxy(dataAdapter); - /** - * Attach the `dataAdapter` to the `req` so that the `syncer` can access it. - */ - this.expressApp.use(function(req, res, next) { - req.dataAdapter = dataAdapter; - - /** - * Proxy `res.end` so we can remove the reference to `dataAdapter` to prevent leaks. - */ - var end = res.end; - res.end = function(data, encoding) { - res.end = end; - req.dataAdapter = null; - res.end(data, encoding); - }; - next(); - }); + this._configured = true; /** * Initialize the Rendr app, accessible at `req.rendrApp`. @@ -108,7 +94,8 @@ Server.prototype.configure = function(fn) { this.expressApp.use(middleware.initApp(this.options.appData, { apiPath: this.options.apiPath, entryPath: this.options.entryPath, - modelUtils: this.options.modelUtils + modelUtils: this.options.modelUtils, + proxyRequest: apiProxyMiddleware.proxyRequest })); /** @@ -120,8 +107,7 @@ Server.prototype.configure = function(fn) { /** * Add the API handler. */ - this.options.apiProxy = this.options.apiProxy || middleware.apiProxy; - this.expressApp.use(this.options.apiPath, this.options.apiProxy(dataAdapter)); + this.expressApp.use(this.options.apiPath, apiProxyMiddleware); /** * Add the routes for everything defined in our routes file. diff --git a/shared/app.js b/shared/app.js index 99cca5fa..d02b7cfb 100644 --- a/shared/app.js +++ b/shared/app.js @@ -44,6 +44,10 @@ module.exports = Backbone.Model.extend({ this.req = this.options.req; } + if (this.options.res) { + this.res = this.options.res; + } + /** * Initialize the `templateAdapter`, allowing application developers to use whichever * templating system they want. diff --git a/shared/syncer.js b/shared/syncer.js index 0a3e2838..83a8aa12 100644 --- a/shared/syncer.js +++ b/shared/syncer.js @@ -58,7 +58,7 @@ function clientSync(method, model, options) { } function serverSync(method, model, options) { - var api, data, urlParts, verb, req; + var api, data, urlParts, verb, req, res; data = _.clone(options.data); data = addApiParams(method, model, data); @@ -66,6 +66,7 @@ function serverSync(method, model, options) { verb = methodMap[method]; urlParts = options.url.split('?'); req = this.app.req; + res = this.app.res; api = { method: verb, @@ -85,7 +86,7 @@ function serverSync(method, model, options) { _.extend(api.query, data); } - req.dataAdapter.request(req, api, function(err, response, body) { + this.app.proxyRequest(req, res, api, {}, function(err, response, body) { var resp; if (err) { resp = {