batch with changeset Problem

Oct 23, 2012 at 3:20 PM
Edited Oct 23, 2012 at 3:36 PM

Hi Alex,

I also note that when creating a batch with a POST then the content-Length header is not set for that data, so my request fails for that POST:

 

--batch_1939-8da1-bf2e Content-Type: multipart/mixed; boundary=changeset_f1ea-5ee2-61fc --changeset_f1ea-5ee2-61fc Content-Type: application/http Content-Transfer-Encoding: binary POST Products HTTP/1.1 Accept: application/json MaxDataServiceVersion: 2.0 DataServiceVersion: 2.0 Content-Type: application/json;odata=verbose {"ID":"9","Name":"Test","Description":"Description","ReleaseDate":"\/Date(1350943200000)\/","Price":"2","Rating":"3"} --changeset_f1ea-5ee2-61fc-- --batch_1939-8da1-bf2e--

Is this a bug or how can I set this header?

The content-length for the complete batch request is set though but not for the batch parts...

 

Oct 24, 2012 at 7:29 PM

Hi Joe,

    The content-length is set by the browser for the entire request. The fact that we don't set the content-length for each of the parts is by design and this because there is no real good way for us to compute the length of the payload in javascript.  And second, the content-length for the part is preferred by the http standard, but not required so we elected no to put it.

    Which server are you using? And what is the failure that you get?

Thanks

Alex Trigo.

Oct 25, 2012 at 11:43 AM
Edited Oct 25, 2012 at 12:05 PM

Hi Alex,

thanks,

I was wondering about that because it is mentioned here in the sample:

http://www.odata.org/documentation/batch#BatchRequestBody

But can't you calculate the content-length with UTF-8 charset yourself?

 

I debugged and hacked a bit in datajs and added it as follows:

var writeRequest = function (request) {
/// <summary>
/// Serializes a request object to a string.
/// </summary>
/// <param name="request" optional="false">Request object to serialize</param>
/// <returns type="String">String representing the serialized request</returns>

var result = (request.method ? request.method : "GET") + " " + request.requestUri + " HTTP/1.1\r\n";
for (var name in request.headers) {
if (request.headers[name]) {
result = result + name + ": " + request.headers[name] + "\r\n";
}
}
 // my modification to add content-length
// code added to add the content-length for each batch part...may be removed for later gateway versions
if (request.body) {

function utf8Len(ch) {
if (ch <= 0x7F) return 1;
if (ch <= 0x7FF) return 2;
if (ch <= 0xFFFF) return 3;
if (ch <= 0x1FFFFF) return 4;
if (ch <= 0x3FFFFFF) return 5;
if (ch <= 0x7FFFFFFF) return 6;
throw new Error("Illegal argument: " + ch);
}

function utf8ByteCount(str) {
var count = 0;
for (var i = 0; i < str.length; i++) {
var ch = str.charCodeAt(i);
count += utf8Len(ch);
}
return count;
}
result += "Content-Length: " + utf8ByteCount(request.body) + "\r\n";
}
 // End modification

result += "\r\n";

if (request.body) {
result += request.body;
}

return result;
};

 

Oct 25, 2012 at 8:02 PM

Hi Joe,

   I see, well the description never mentions the Content-Length at all; though the sample has it... but that is a sample and they are not always accurate.  Yes, you can calculate the length if your know the encoding... but it is not guaranteed that you know the ecoding before hand or that you will be using UTF-8 always. I know UTF-8 is very popular and seems everything is gravitating towards that. 

   I like your solution above, but I feel that computing this is just extra overhead.  Does the gateway requires content-length to understand a batch payload?? Knowing the content-length is very helpful, but there should always be the option to scan the part delimiters in the body of the request.

Thanks,

Alex Trigo. 

Oct 26, 2012 at 9:37 AM

Hi Alex,

 

thanks for your reply.

 Yes afaik gateway needs that content-length but I guess they fixed it now for newer versions.

Because of UTF-8: I've read that W3C XMLHTTPRequest standard specifies POST data will always be encoded with the UTF-8 .

Well, don't know if this is right.