[483] | 1 | define(["dojo/_base/kernel"], function(dojo){ |
---|
| 2 | dojo.getObject("io.httpParse", true, dojox); |
---|
| 3 | |
---|
| 4 | dojox.io.httpParse = function(/*String*/httpStream, /*String?*/topHeaders,/*Boolean?*/ partial){ |
---|
| 5 | // summary: |
---|
| 6 | // Parses an HTTP stream for a message. |
---|
| 7 | // httpStream: |
---|
| 8 | // HTTP stream to parse |
---|
| 9 | // topHeaders: |
---|
| 10 | // Extra header information to add to each HTTP request (kind of HTTP inheritance) |
---|
| 11 | // partial: |
---|
| 12 | // A true value indicates that the stream may not be finished, it may end arbitrarily in mid stream. |
---|
| 13 | // The last XHR object will have a special property _lastIndex that indicates the how far along |
---|
| 14 | // the httpStream could be successfully parsed into HTTP messages. |
---|
| 15 | // returns: |
---|
| 16 | // Returns an array of XHR-like object for reading the headers for each message |
---|
| 17 | // |
---|
| 18 | var xhrs=[]; |
---|
| 19 | var streamLength = httpStream.length; |
---|
| 20 | do{ |
---|
| 21 | var headers = {}; |
---|
| 22 | var httpParts = httpStream.match(/(\n*[^\n]+)/); |
---|
| 23 | if(!httpParts){ |
---|
| 24 | return null; |
---|
| 25 | } |
---|
| 26 | httpStream = httpStream.substring(httpParts[0].length+1); |
---|
| 27 | httpParts = httpParts[1]; |
---|
| 28 | var headerParts = httpStream.match(/([^\n]+\n)*/)[0]; |
---|
| 29 | |
---|
| 30 | httpStream = httpStream.substring(headerParts.length); |
---|
| 31 | var headerFollowingChar = httpStream.substring(0,1); |
---|
| 32 | httpStream = httpStream.substring(1); |
---|
| 33 | headerParts = (topHeaders || "") + headerParts; |
---|
| 34 | var headerStr = headerParts; |
---|
| 35 | headerParts = headerParts.match(/[^:\n]+:[^\n]+\n/g); // parse the containing and contained response headers with the contained taking precedence (by going last) |
---|
| 36 | for(var j = 0; j < headerParts.length; j++){ |
---|
| 37 | var colonIndex = headerParts[j].indexOf(':'); |
---|
| 38 | headers[headerParts[j].substring(0,colonIndex)] = headerParts[j].substring(colonIndex+1).replace(/(^[ \r\n]*)|([ \r\n]*)$/g,''); // trim |
---|
| 39 | } |
---|
| 40 | |
---|
| 41 | httpParts = httpParts.split(' '); |
---|
| 42 | var xhr = { // make it look like an xhr object, at least for the response part of the API |
---|
| 43 | status : parseInt(httpParts[1],10), |
---|
| 44 | statusText : httpParts[2], |
---|
| 45 | readyState : 3, // leave it at 3 until we get a full body |
---|
| 46 | getAllResponseHeaders : function(){ |
---|
| 47 | return headerStr; |
---|
| 48 | }, |
---|
| 49 | getResponseHeader : function(name){ |
---|
| 50 | return headers[name]; |
---|
| 51 | } |
---|
| 52 | }; |
---|
| 53 | var contentLength = headers['Content-Length']; |
---|
| 54 | var content; |
---|
| 55 | if(contentLength){ |
---|
| 56 | if(contentLength <= httpStream.length){ |
---|
| 57 | content = httpStream.substring(0,contentLength); |
---|
| 58 | }else{ |
---|
| 59 | return xhrs; // the content is not finished |
---|
| 60 | } |
---|
| 61 | }else if((content = httpStream.match(/(.*)HTTP\/\d\.\d \d\d\d[\w\s]*\n/))){ // assign content |
---|
| 62 | // if we spot another HTTP message coming up, we will just assign all the in between text to the content |
---|
| 63 | content = content[0]; |
---|
| 64 | }else if(!partial || headerFollowingChar == '\n'){ |
---|
| 65 | // if we have to finish |
---|
| 66 | content = httpStream; |
---|
| 67 | }else{ |
---|
| 68 | return xhrs; |
---|
| 69 | } |
---|
| 70 | xhrs.push(xhr); // add it to the list, since it is a full HTTP message |
---|
| 71 | httpStream = httpStream.substring(content.length); // move along the stream |
---|
| 72 | xhr.responseText = content; |
---|
| 73 | xhr.readyState = 4; |
---|
| 74 | xhr._lastIndex = streamLength - httpStream.length; // need to pick up from where we left on streaming connections |
---|
| 75 | }while(httpStream); |
---|
| 76 | return xhrs; |
---|
| 77 | }; |
---|
| 78 | |
---|
| 79 | return dojox.io.httpParse; |
---|
| 80 | |
---|
| 81 | }); |
---|