@sap/xsodata
Version:
Expose data from a HANA database as OData V2 service with help of .xsodata files.
123 lines (97 loc) • 3.76 kB
JavaScript
;
/**
* Add <uriTree> attribute to <context>
* <uriTree> = {
* rawUrl : "->original url"
* rawUrlParts : "->splitted rawUrl"
* xsoFile : "->file of adressed xsoFile (usually the first segment)
* segments : [
* {
* raw : "->segment encoded"
* decoded : "->segment decoded"
* }
* }
* Uses <context.request.url>
* @type {exports}
*/
//Includes
var url = require('url');
var Http404_NotFound = require('./../utils/errors/http/notFound');
var _ = require('lodash');
var Measurement = require('./../utils/measurement');
function extractSegments(pathname) {
var i,
s = pathname.split('/'),
segments = {};
segments.raw = [];
// remove first empty string from "/<service_name>/..."
if (s[0].length === 0) {
s.shift();
}
// remove the last element if URI ends with "/"
if (s[s.length - 1] === "") {
s.pop();
}
//remove empty segments
for ( i = 0; i < s.length; i++) {
segments.raw.push(s[i]);
}
//decode segments
segments.decoded = [];
for ( i = 0; i < segments.raw.length; i++) {
segments.decoded.push(decodeURIComponent(segments.raw[i]));
}
return segments;
}
exports.prepareUri = function (context, asyncDone) {
//TODO check for multiple service segments
///E.g. ///url
context.logger.silly('http', 'prepareUri');
var uriTree = context.uriTree = {};
uriTree.rawUrl = context.request.url; //may contain a xsodata file in first segment or not
uriTree.rawUrlParts = Measurement.measureSync(url.parse, uriTree.rawUrl, true, 'url.parse');
uriTree.queryParameters = uriTree.rawUrlParts.query;
//read segments
uriTree.segments = Measurement.measureSync(extractSegments, uriTree.rawUrlParts.pathname, 'extractSegments');
if (uriTree.segments.length === 0) {
return asyncDone(new Http404_NotFound('Service definition missing'), context);
}
if (context.batchContext) {
uriTree.xsoFile = context.batchContext.parentContext.uriTree.xsoFile || '';
uriTree.baseUrl = context.batchContext.parentContext.uriTree.baseUrl;
return asyncDone(null, context);
}
if (context.servingDirectory) {
//first segment MUST BE xsodata filename
//remove the .xsodata from the segments
uriTree.xsoFile = uriTree.segments.decoded[0] || '';
uriTree.segments.decoded.shift();
uriTree.segments.raw.shift();
//build baseUrl
var urlData = {
protocol: context.request.urlData.proto,
host: context.request.urlData.host,
pathname: determineBasePath(context.request.baseUrl + '/' + uriTree.xsoFile, uriTree.segments.decoded, context.request.urlData)
};
uriTree.baseUrl = Measurement.measureSync(url.format, urlData, 'url.format');
return asyncDone(null, context);
}
//USE Case this instance of the xsodata handler only processes a single xsodata file
//so the name of this odata file MUST NOT inside the url
var tmp2 = {
protocol: context.request.urlData.proto,
host: context.request.urlData.host,
pathname: determineBasePath(context.request.baseUrl, uriTree.segments.decoded, context.request.urlData)
};
uriTree.baseUrl = Measurement.measureSync(url.format, tmp2, 'url.format');
return asyncDone(null, context);
};
//For unit testing
exports._getSegments = extractSegments;
function determineBasePath(uriPrefix, urlSegmentsNoXso, urlData){
if (urlData.forwarded){
var fSegs = extractSegments(urlData.path).decoded;
return _.dropRight(fSegs, urlSegmentsNoXso.length).join('/') + '/';
}
return uriPrefix + '/';
}