xhrMultiPart.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| IBM Cognos Products: Viewer
  5. *| (C) Copyright IBM Corp. 2001, 2011
  6. *|
  7. *| US Government Users Restricted Rights - Use, duplication or
  8. *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. *|
  10. *+------------------------------------------------------------------------+
  11. */
  12. var xhrMultiPart = {};
  13. xhrMultiPart.Boundary = "{part}";
  14. xhrMultiPart.Queue = null;
  15. xhrMultiPart.QueueMaximum = 3;
  16. xhrMultiPart.TimerId = null;
  17. xhrMultiPart.TimeSlice = 500;
  18. //TODO: Might want to put this in the viewerconfig file so the user can turn it on/off
  19. xhrMultiPart.active = false;
  20. /*
  21. * At the moment, this function supports all of the members of dojo.__XhrArgs except:
  22. * - form
  23. * - handleAs
  24. * - timeout
  25. * - user
  26. * - password
  27. * - failOk
  28. *
  29. * See http://docs.dojocampus.org/dojo/xhrPost for details
  30. */
  31. xhrMultiPart.Post = function(/*dojo.__XhrArgs*/args) {
  32. var dfd = null;
  33. if (xhrMultiPart.active)
  34. {
  35. if (args instanceof Object)
  36. {
  37. if (xhrMultiPart.Queue === null) {
  38. xhrMultiPart.Queue = [];
  39. if (xhrMultiPart.TimeSlice > 0) {
  40. xhrMultiPart.TimerId = setTimeout(xhrMultiPart.Send, xhrMultiPart.TimeSlice);
  41. }
  42. }
  43. if (typeof bux !== "undefined" && bux && bux._prepareArgs) {
  44. args = bux._prepareArgs(args);
  45. }
  46. xhrMultiPart.Queue.push(args);
  47. if (args.sync || xhrMultiPart.Queue.length >= xhrMultiPart.QueueMaximum) {
  48. dfd = xhrMultiPart.Send();
  49. }
  50. }
  51. }
  52. return dfd;
  53. };
  54. xhrMultiPart.Send = function () {
  55. var dfd = null;
  56. if (xhrMultiPart.TimerId) {
  57. clearTimeout(xhrMultiPart.TimerId);
  58. xhrMultiPart.TimerId = null;
  59. }
  60. var requests = null;
  61. var len = 0;
  62. if (xhrMultiPart.Queue) {
  63. requests = xhrMultiPart.Queue;
  64. len = requests.length;
  65. xhrMultiPart.Queue = null;
  66. }
  67. if (len > 0 && requests !== null) {
  68. var boundary = xhrMultiPart.Boundary;
  69. var newLine = "\r\n";
  70. var separator = "--";
  71. var partStart = newLine + separator + boundary + newLine;
  72. var partEnd = newLine + newLine;
  73. var requestEnd = newLine + separator + boundary + separator + newLine;
  74. var headerEnd = newLine + newLine;
  75. var postUrl;
  76. if (typeof bux !== "undefined" && bux && bux._base) {
  77. dojo["require"]("bux.Services"); //@lazyload
  78. postUrl = bux.Services.getGateway();
  79. }
  80. else {
  81. postUrl = requests[0].url;
  82. }
  83. postUrl += "/batchviewer";
  84. var request = "";
  85. for (var i = 0; i < len; i++) {
  86. var currentRequest = requests[i];
  87. request += partStart;
  88. request += "Content-disposition: form-data; name=\"field" + (i + 1) + "\"";
  89. if (currentRequest.headers) {
  90. for (var item in currentRequest.headers) {
  91. request += newLine + item + ": " + currentRequest.headers[item];
  92. }
  93. }
  94. request += headerEnd;
  95. if (currentRequest.content) {
  96. for (var iContent in currentRequest.content) {
  97. request += iContent + "=" + encodeURIComponent(currentRequest.content[iContent]) + "&";
  98. }
  99. }
  100. request += partEnd;
  101. }
  102. request += requestEnd;
  103. var args = {
  104. url: postUrl,
  105. postData: request,
  106. sync: len === 1 && requests[0].sync ? true: false, //Do it asynch unless there is only one request and it is flagged as synchronous
  107. preventCache: true,
  108. headers: {"Content-Type": "multipart/form-data; charset=UTF-8; boundary=\"" + xhrMultiPart.Boundary +"\""}
  109. };
  110. dfd = xhrMultiPart.SetupResponseHandler(args, requests);
  111. }
  112. return dfd;
  113. };
  114. xhrMultiPart.SetupResponseHandler = function(args, requests) {
  115. var dfdpromise = dojo.xhrPost(args).promise;
  116. var len = requests.length;
  117. for (var i = 0; i < len; i++) {
  118. var currentRequest = requests[i];
  119. currentRequest.currentHandler = dfd;
  120. if (currentRequest.load) {
  121. dfdpromise = dfdpromise.then(
  122. /*callback*/ dojo.hitch(currentRequest, function(response){
  123. var parsedResponse = xhrMultiPart.GetResponsePart(response, this);
  124. this.load(parsedResponse.currentPart ? parsedResponse.currentPart : parsedResponse);
  125. return parsedResponse;
  126. })
  127. );
  128. }
  129. if (currentRequest.error) {
  130. dfdpromise = dfdpromise.then(
  131. /*callback*/ null,
  132. /* errback*/ dojo.hitch(currentRequest, function(response){
  133. var parsedResponse = xhrMultiPart.GetResponsePart(response, this);
  134. this.error(parsedResponse.currentPart ? parsedResponse.currentPart : parsedResponse);
  135. return parsedResponse;
  136. })
  137. );
  138. }
  139. var fResponseParser = null;
  140. if (currentRequest.handle) {
  141. fResponseParser = dojo.hitch(currentRequest, function(response){
  142. var parsedResponse = xhrMultiPart.GetResponsePart(response, this);
  143. this.handle(parsedResponse.currentPart ? parsedResponse.currentPart : parsedResponse);
  144. return parsedResponse;
  145. });
  146. dfdpromise = dfdpromise.then(
  147. /*callback*/ fResponseParser,
  148. /* errback*/ fResponseParser
  149. );
  150. }
  151. //Ok, we are done with this part...shift out it's result and move it on down the line!
  152. fResponseParser = dojo.hitch(currentRequest, function(response){
  153. var result = {
  154. currentPart: {},
  155. otherParts: {}
  156. };
  157. var parsedResponse = xhrMultiPart.GetResponsePart(response, this);
  158. if (parsedResponse instanceof Error) {
  159. result = parsedResponse;
  160. }
  161. else if (parsedResponse && parsedResponse.otherParts) {
  162. result.currentPart = parsedResponse.otherParts.shift();
  163. result.otherParts = parsedResponse.otherParts;
  164. }
  165. return result;
  166. });
  167. dfdpromise = dfdpromise.then(
  168. /*callback*/ fResponseParser,
  169. /* errback*/ fResponseParser
  170. );
  171. }
  172. return dfdpromise;
  173. };
  174. xhrMultiPart.GetResponsePart = function(response, request) {
  175. var result;
  176. if (dojo.isString(response)) {
  177. result = xhrMultiPart.ParseResponse(response, request);
  178. }
  179. else {
  180. result = response;
  181. }
  182. return result;
  183. };
  184. xhrMultiPart.ParseResponse = function(response, request){
  185. var boundaryRegx = /boundary\s*=\s*\"?([^\"]*)\"?/;
  186. var boundMatch = request.currentHandler.ioArgs.xhr.getResponseHeader("X-C").match(boundaryRegx);
  187. if (!boundMatch) {
  188. //TODO: Localize
  189. throw new Error("No boundary specified in Content-Type response header");
  190. }
  191. var boundary = boundMatch[1];
  192. var newLine = "\r\n";
  193. var separator = "--";
  194. var splitterRegx = new RegExp(separator + boundary + "(" + newLine + "|" + separator + ")", "mg");
  195. var respParts = response.split(splitterRegx);
  196. if (respParts && respParts.length === 1) {
  197. //TODO: Localize
  198. throw new Error("Boundary specified in Content-Type response header is not found in response body");
  199. }
  200. var parts = [];
  201. var len = respParts.length;
  202. for (var i = 0; i < len; i++) {
  203. var part = respParts[i];
  204. if (part.length > 0 && part !== separator && part !== newLine) {
  205. part = dojo.trim(part);
  206. var partObj = xhrMultiPart.BuildPartObject(part);
  207. parts.push(partObj);
  208. }
  209. }
  210. return {
  211. currentPart: parts.shift(),
  212. otherParts: parts
  213. };
  214. };
  215. xhrMultiPart.BuildPartObject = function(part) {
  216. var newLine = "\r\n";
  217. var partPieces = part.split(newLine + newLine, 2);
  218. var headers = null;
  219. var content = null;
  220. if (partPieces.length == 1) {
  221. content = partPieces[0];
  222. } else {
  223. headers = partPieces[0];
  224. content = partPieces[1];
  225. }
  226. var headerObj = xhrMultiPart.ParseHeaders(headers);
  227. var status;
  228. if (headerObj["X-Status-Code"]) {
  229. status = parseInt(headerObj["X-Status-Code"], 10);
  230. } else {
  231. //TODO: Assume failure or assume success?
  232. status = 200;
  233. }
  234. var partObj = {
  235. status: status,
  236. responseText: dojo.trim(content),
  237. headers: headerObj,
  238. getResponseHeader: function(header) { return this.headers[header.toLowerCase()]; }
  239. };
  240. return partObj;
  241. };
  242. xhrMultiPart.ParseHeaders = function(headers) {
  243. var headerObj = {};
  244. if (headers !== null) {
  245. var newLine = "\r\n";
  246. var headerArr = headers.split(newLine);
  247. for (var j = 0; j < headerArr.length; j++) {
  248. var currentHeader = headerArr[j];
  249. var headerTuple = currentHeader.split(":");
  250. if (headerTuple.length == 2) {
  251. headerObj[headerTuple[0].toLowerCase()] = headerTuple[1];
  252. }
  253. }
  254. }
  255. return headerObj;
  256. };