From 4c1140118d6635d5cdb98599415382bc0b5d15d1 Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Tue, 27 Jul 2010 13:31:19 -0600 Subject: [PATCH] Properly handle asynchronous bodies --- lib/jsgi/media.js | 12 ++++--- lib/media.js | 6 ++-- lib/media/json.js | 2 +- lib/media/message/json.js | 72 ++++++++++++++++++++------------------- 4 files changed, 49 insertions(+), 43 deletions(-) diff --git a/lib/jsgi/media.js b/lib/jsgi/media.js index 5f0e1f4..6af8415 100644 --- a/lib/jsgi/media.js +++ b/lib/jsgi/media.js @@ -6,7 +6,7 @@ */ exports.MediaConverter = MediaConverter; var METHOD_HAS_BODY = require("./methods").METHOD_HAS_BODY, - onFile = require("../media").onFile, + mediaModule = require("../media"), when = require("promised-io/promise").when; function MediaConverter(mediaSelector, nextApp){ @@ -32,7 +32,7 @@ function MediaConverter(mediaSelector, nextApp){ request.body[parts[0].trim()] = parts[1].trim().replace(/"/g,''); } }); - response = when(onFile(request.body), function(){ + response = when(mediaModule.onFile(request.body), function(){ return nextApp(request); }); // funnel errors to the response }else{ @@ -53,13 +53,15 @@ function MediaConverter(mediaSelector, nextApp){ } if(typeof body.callNextApp === "function"){ var response = body.callNextApp(nextApp); - }else{ - request.body= body; } } } - var response = response || nextApp(request); + var response = response || when(body, function(body){ + request.body = body + return nextApp(request); + }); + request.variedOn = ""; // let middleware add varied on headers to the request so we can efficiently add them all at once diff --git a/lib/media.js b/lib/media.js index 759caa3..cfe78a8 100644 --- a/lib/media.js +++ b/lib/media.js @@ -5,6 +5,7 @@ */ var model = require("perstore/model"), + when = require("promised-io/promise").when, Media = exports.Media = function(media){ Media.instances[media.mediaType] = media; }; @@ -102,10 +103,11 @@ exports.getColumnsToExport = function(request, item){ exports.forEachableToString = function(input){ var strings = []; - input.forEach(function(block){ + return when(input.forEach(function(block){ strings.push(block); + }), function(){ + return strings.join(""); }); - return strings.join(""); }; exports.onFile = function(file){ diff --git a/lib/media/json.js b/lib/media/json.js index 3e74364..686cd51 100644 --- a/lib/media/json.js +++ b/lib/media/json.js @@ -13,7 +13,7 @@ Media({ }, serialize: StreamingSerializer(JSON.stringify), deserialize: function(inputStream, request){ - return JSONExt.parse(forEachableToString(inputStream)); + return when(forEachableToString(inputStream), JSONExt.parse); } }); diff --git a/lib/media/message/json.js b/lib/media/message/json.js index 43d613e..c766455 100644 --- a/lib/media/message/json.js +++ b/lib/media/message/json.js @@ -17,44 +17,46 @@ Media({ return 0.75; }, deserialize: function(body, request){ - body = JSONExt.parse(forEachableToString(body)); + body = when(forEachableToString(body), JSONExt.parse); return { callNextApp: function(nextApp){ - if(!(body instanceof Array)){ - body = [body]; - } - var responses = []; - var clientConnection = getClientConnection(request); - body.forEach(function(message){ - message.__proto__ = request; - if(!("to" in message)){ - message.to = ""; - } - var pathInfo = message.to.charAt(0) === '/' ? message.to : request.pathInfo.substring(0, request.pathInfo.lastIndexOf('/') + 1) + message.to; - while(lastPath !== pathInfo){ - var lastPath = pathInfo; - pathInfo = pathInfo.replace(/\/[^\/]*\/\.\.\//,'/'); - } - message.pathInfo = pathInfo; - var response = nextApp(message); - response.pathInfo = pathInfo; - if(response.body && typeof response.body.observe === "function"){ - clientConnection.exportMore = true; - response.body.observe(function(message){ - message.from = message.channel; - clientConnection.send(message); - }); - }else{ - responses.push(response); - } - }); - return when(all(responses), function(responses){ - return { - status: clientConnection.exportMore ? 202: 200, - headers: {}, - messages: true, - body: responses + return when(body, function(body){ + if(!(body instanceof Array)){ + body = [body]; } + var responses = []; + var clientConnection = getClientConnection(request); + body.forEach(function(message){ + message.__proto__ = request; + if(!("to" in message)){ + message.to = ""; + } + var pathInfo = message.to.charAt(0) === '/' ? message.to : request.pathInfo.substring(0, request.pathInfo.lastIndexOf('/') + 1) + message.to; + while(lastPath !== pathInfo){ + var lastPath = pathInfo; + pathInfo = pathInfo.replace(/\/[^\/]*\/\.\.\//,'/'); + } + message.pathInfo = pathInfo; + var response = nextApp(message); + response.pathInfo = pathInfo; + if(response.body && typeof response.body.observe === "function"){ + clientConnection.exportMore = true; + response.body.observe(function(message){ + message.from = message.channel; + clientConnection.send(message); + }); + }else{ + responses.push(response); + } + }); + return when(all(responses), function(responses){ + return { + status: clientConnection.exportMore ? 202: 200, + headers: {}, + messages: true, + body: responses + } + }); }); } };