UNPKG

@sap/xsodata

Version:

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

131 lines (109 loc) 4.23 kB
'use strict'; var async = require("async"); var NotSupportedError = require("./../../utils/errors/http/notSupported"); var contentTypeTools = require("./../../utils/checkContentType"); var api = module.exports = { validate: validate, _validateHttpHeader: _validateHttpHeader, _validateAcceptHeader: _validateAcceptHeader }; /** * Validates the http request. Validation is done by validate http accept header. * *@param {Object} context The xsodata context *@param {Function} done Callback called on finish. Expect following signature: * function(error, context){} */ function validate(context, done) { var validationStrategy = getValidationStrategy(context); context.logger.silly("httpRequestValidator", "validate"); async.waterfall(validationStrategy, function (err, result) { done(err, result); }); } /** * Validates the http request header in general. I.e. if headers exists. * *@param {Object} context The xsodata context *@param {Function} done Callback called on finish. Expect following signature: * function(error, context){} */ function _validateHttpHeader(context, done) { context.logger.silly("httpRequestValidator", "validateHttpHeader"); if (!context.request || !context.request.headers) { return done(new NotSupportedError("A valid http Accept header must be provided")); } done(null, context); } /** * Validates the http request accept header. This method validates if the current provided * http accept header is available and is supported. * *@param {Object} context The xsodata context *@param {Function} done Callback called on finish. Expect following signature: * function(error, context){} */ function _validateAcceptHeader(context, done) { var acceptHeader = context.request.headers["accept"] || context.request.headers["Accept"]; context.logger.silly("httpRequestValidator", "validateAcceptHeader"); if (!acceptHeader) { return done(new NotSupportedError("A valid http Accept header must be provided")); } var contentType; try { contentType = contentTypeTools.checkEntry(context.request, getCustomFormat(context)); } catch (ex) { return done(new NotSupportedError("Provided http Accept header '" + acceptHeader + "' is not supported", context, ex)); } if (contentType === contentTypeTools.cTypes.ctJson) { return done(null, context); } return done(new NotSupportedError("Provided http Accept header '" + acceptHeader + "' is not supported")); } /** * Returns true if the current request is a batch request. A request is a batch request if * the request url ends with $batch. * *@param {Object} context The xsodata context *@returns {Boolean} True if current request url endwith $batch else false */ function isBatchRequest(context) { if (!context.uriTree.segments.decoded || context.uriTree.segments.decoded.length === 0) { return false; // call to service document } return context.uriTree.segments.decoded[0].toLowerCase() === "$batch"; } /** * Returns the current validation strategy. The validation strategy which will be used for * validation depends on the kind of request sent. * *@param {Object} context The xsodata context */ function getValidationStrategy(context) { var initialStrategy; context.logger.silly("httpRequestValidator", "getValidationStrategy"); // Initial strategy is needed to inject context into async.waterfall() initialStrategy = [ function (callback) { callback(null, context); } ]; if (context.request.method === "POST" && !isBatchRequest(context)) { // Adding validation strategies if http method is POST and request is not a batch req. return initialStrategy.concat([ api._validateHttpHeader, api._validateAcceptHeader ]); } return initialStrategy; } /** * Returns value of the custom 'format' URL parameter. */ function getCustomFormat(context) { var queryParameters = context.uriTree.queryParameters; if (queryParameters) { return queryParameters['format']; } }