UNPKG

@sap/xsodata

Version:

Expose data from a HANA database as OData V2 service with help of .xsodata files.

173 lines (150 loc) 4.81 kB
'use strict'; const utils = require('./../utils'); const batchObjects = require('./batchObjects'); exports.getBoundary = function (headerValue) { const l = headerValue.split(';'); for (const element of l) { const ll = element.split('='); if (ll[0].trim() === 'boundary') { return ll[1]; } } }; function readAppHttp(batchContent, boundary) { const headers = {}; const payload = []; let state = 0; //read url const url = batchContent.readLine(); state = 1; //read header let 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 { const 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) { const boundaryNext = boundary; const boundaryEnd = boundary + '--'; const headers = {}; let content; let state = 1; //read header let 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 { const 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;') ) { const 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; } function readHeader(line) { const colPos = line.indexOf(':'); if (colPos === -1) { throw new Error('Invalid header "content-type" in batch part'); } const s0 = line.substr(0, colPos); const s1 = line.substr(colPos + 1); return { name: s0.toLowerCase(), value: s1.trim(), }; } function parseBatch(content, boundary, type) { const boundaryNext = '--' + boundary; const boundaryEnd = '--' + boundary + '--'; const batch = new batchObjects.Batch(type); let part; let 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' ); };