UNPKG

@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
'use strict'; /** * 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 + '/'; }