@sap/xsodata
Version:
Expose data from a HANA database as OData V2 service with help of .xsodata files.
150 lines (122 loc) • 4.51 kB
JavaScript
;
var utils = require('./../utils');
var batchObjects = require('./batchObjects');
exports.getBoundary = function (headerValue) {
var l = headerValue.split(';');
for (var i = 0; i < l.length; i++) {
var ll = l[i].split('=');
if (ll[0].trim() === 'boundary') {
return ll[1];
}
}
};
function readAppHttp(batchContent, boundary) {
var headers = {};
var payload = [];
var state = 0; //read url
var url = batchContent.readLine();
state = 1; //read header
var line = batchContent.lookLine();
while ((line !== null && line !== undefined) && line.indexOf(boundary) !== 0) {
if (state === 1) {
if (line.length === 0) {
state = 2; //read body
batchContent.inc();
} else {
var h = readHeader(line);
headers[h.name] = h.value;
batchContent.inc();
}
} else if (state === 2) {
payload.push(line);
batchContent.inc();
}
line = batchContent.lookLine();
}
if (line === undefined) {
throw new Error("Invalid boundary while parsing batch request. Expect boundary " + boundary);
}
return new batchObjects.AppHttp(url, headers, payload);
}
function parsePart(batchContent, boundary) {
var boundaryNext = boundary;
var boundaryEnd = boundary + '--';
var headers = {};
var content;
var state = 1; //read header
var line = batchContent.lookLine();
while ((line !== null && line !== undefined) && line !== boundaryNext && line !== boundaryEnd) {
if (state === 1) {
if (line.length === 0) {
state = 2; //read body
batchContent.inc();
} else {
var h = readHeader(line);
headers[h.name] = h.value;
batchContent.inc();
}
} else if (state === 2) {
if (!headers['content-type']) {
throw new Error('Missing header "content-type" in batch part');
} else if (headers['content-type'] === 'application/http') {
content = readAppHttp(batchContent, boundary);
} else if (utils.startsWith(headers['content-type'], 'multipart/mixed;')) {
var changeSetBoundary = exports.getBoundary(headers['content-type']);
content = parseBatch(batchContent, changeSetBoundary, "changeset");
} else {
//TODO not supported
}
}
line = batchContent.lookLine();
}
if (line === undefined) {
throw new Error("Invalid boundary while parsing batch request. Expect boundary " + boundary);
}
return content;
//return new batchObjects.BatchPart(headers, content);
}
function readHeader(line) {
var colPos = line.indexOf(':');
if (colPos === -1) {
throw new Error('Invalid header "content-type" in batch part');
}
var s0 = line.substr(0, colPos);
var s1 = line.substr(colPos + 1);
return {
name: s0.toLowerCase(),
value: s1.trim()
};
}
function parseBatch(content, boundary, type) {
var boundaryNext = '--' + boundary;
var boundaryEnd = '--' + boundary + '--';
var batch = new batchObjects.Batch(type);
var part;
var line = content.readLine();
while ((line !== null && line !== undefined) && line !== boundaryNext) { //read lines before first boundary
line = content.readLine();
}
if (line === undefined) {
throw new Error("Invalid boundary while parsing batch request");
}
//line is now read boundary
line = content.lookLine(); //read line behind
while ((line !== null && line !== undefined) && line !== boundaryEnd) {
part = parsePart(content, boundaryNext);
batch.parts.push(part);
line = content.lookLine(); //now on boundary
if (line === boundaryNext) {
line = content.readLine();//consume boundaryNext
}
}
content.readLine();//consume boundaryEnd
line = content.lookLine(); //read line behind
while ((line !== null && line !== undefined) && line.length === 0) { //read empty lines after first boundaryend
content.readLine();
line = content.lookLine();
}
return batch;
}
exports.convertBatch = function (payload, boundary) {
return parseBatch(new batchObjects.BatchContent(payload), boundary, "batch");
};