UNPKG

@sap/xsodata

Version:

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

152 lines (133 loc) 4.54 kB
'use strict'; const async = require('async'); const NotSupportedError = require('./../../utils/errors/http/notSupported'); const contentTypeTools = require('./../../utils/checkContentType'); const 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) { const 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) { const 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') ); } let 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) { let 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) { const queryParameters = context.uriTree.queryParameters; if (queryParameters) { return queryParameters['format']; } }