UNPKG

@sap/xsodata

Version:

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

216 lines (187 loc) 7.86 kB
'use strict'; var jsonBuilder = require('./../serializer/json'); var contentTypeTools = require('./../utils/checkContentType'); var InternalError = require('./../utils/errors/internalError'); var AtomSerializer = require('./../serializer/atomSerializer'); var NotImplemented = require('./../utils/errors/http/notImplemented'); var odataUriType = require('../uri/uriType'); // Name of the URL parameter, which indicates that the service response should be in Atom format. // This is a temporary solution, which is used until the OData content type negotiation is not implemented. var CUSTOM_FORMAT_PARAMETER = "format"; // Value of the custom 'format' parameter, which indicates that the service response should be in Atom format. var CUSTOM_ATOM_FORMAT_NAME = "atomXml"; exports.serializeNoContent = function (context, asyncDone) { var responseHeaders = {}; addETagHeader(context, responseHeaders); context.response.writeHead(204, responseHeaders); return asyncDone(null, context); }; //Code exports.serializeData = function (context, asyncDone) { try { var uriType = odataUriType.determineUriType(context); var requestedType = getRequestedType(context); var responseContentType = getResponseContentType(requestedType, context, uriType); var serializer = getSerializer(requestedType, context); var responseBody = createResponseBody(context, uriType, serializer); var responseHeaders = createResponseHeaders(context, responseContentType); writeResponse(context, responseBody, responseHeaders); return asyncDone(null, context); } catch (err) { return asyncDone(err, context); } }; function createResponseHeaders(context, responseContentType) { var headers = { "Content-Type": responseContentType }; var cacheControl = getCacheControlHeader(context); if (cacheControl) { headers["cache-control"] = cacheControl; } addETagHeader(context, headers); return headers; } function addETagHeader(context, headers) { var dbSegment = context.oData.dbSegmentLast; if (dbSegment.etagHeader) { headers.ETag = 'W/"' + dbSegment.etagHeader + '"'; } } function getCacheControlHeader(context) { if (context.gModel) { return context.gModel.getSetting('content', 'cache-control'); } } function writeResponse(context, responseBody, responseHeaders) { context.response.writeHead(200, responseHeaders); context.response.write(responseBody); } function getInlineCount(context) { if (context.oData.systemQueryParameters.inlinecount === true) { var dbSegment = context.oData.dbSegmentLast; var rows = dbSegment.getRowsWithGenKey(); var count = rows[0] && rows[0]['0count'] || dbSegment.sql.countRows[0] && dbSegment.sql.countRows[0]['c']; return String(count); } } /** * Serializes the last DB segment from the specified context using the specified serializer in accordance with the * specified uriType. * @returns HTTP response body containing the serialized data. */ function createResponseBody(context, uriType, serializer) { var dbSegment = context.oData.dbSegmentLast; switch (uriType) { case odataUriType.URI1: case odataUriType.URI6B: return serializer.serializeFeed(dbSegment, getInlineCount(context)); case odataUriType.URI2: case odataUriType.URI6A: return serializer.serializeEntity(dbSegment); case odataUriType.URI5A: return serializer.serializeProperty(dbSegment); case odataUriType.URI5B: return serializePropertyValue(dbSegment); case odataUriType.URI7A: return serializer.serializeEntity(dbSegment); case odataUriType.URI7B: return serializer.serializeFeed(dbSegment, getInlineCount(context)); case odataUriType.URI15: case odataUriType.URI16: return serializeCountValue(context, dbSegment); default: throw new NotImplemented("Request URI is not supported.", context); } } function getSerializer(contentType, context) { if (contentType === CUSTOM_ATOM_FORMAT_NAME) { return new AtomSerializer(context); } else { return new jsonBuilder.JsonBuilder(context); } } function getRequestedType(context) { var customFormat = getCustomFormat(context); if (customFormat && customFormat === CUSTOM_ATOM_FORMAT_NAME) { return CUSTOM_ATOM_FORMAT_NAME; } return context.oData.systemQueryParameters.format; } function getResponseContentType(requestedType, context, uriType) { var contentType; switch (uriType) { case odataUriType.URI1: case odataUriType.URI6B: // custom 'format' parameter takes precedence over the $format option and the Accept header. if (requestedType === CUSTOM_ATOM_FORMAT_NAME) { contentType = contentTypeTools.cTypes.ctAtomFeed; } else { contentType = contentTypeTools.checkFeed(context.request, requestedType); } break; case odataUriType.URI2: case odataUriType.URI6A: // custom 'format' parameter takes precedence over the $format option and the Accept header. if (requestedType === CUSTOM_ATOM_FORMAT_NAME) { contentType = contentTypeTools.cTypes.ctAtomEntry; } else { contentType = contentTypeTools.checkEntry(context.request, requestedType); } break; case odataUriType.URI5A: contentType = contentTypeTools.checkProperty(context.request, requestedType); break; case odataUriType.URI5B: contentType = contentTypeTools.checkValue(context.request, requestedType); break; case odataUriType.URI7A: // custom 'format' parameter takes precedence over the $format option and the Accept header. if (requestedType === CUSTOM_ATOM_FORMAT_NAME) { contentType = contentTypeTools.cTypes.ctAtomEntry; } else { contentType = contentTypeTools.checkEntry(context.request, requestedType); } break; case odataUriType.URI7B: // custom 'format' parameter takes precedence over the $format option and the Accept header. if (requestedType === CUSTOM_ATOM_FORMAT_NAME) { contentType = contentTypeTools.cTypes.ctAtomFeed; } else { contentType = contentTypeTools.checkFeed(context.request, requestedType); } break; case odataUriType.URI15: case odataUriType.URI16: contentType = contentTypeTools.checkCount(context.request, requestedType); break; default: throw new NotImplemented("Request URI is not supported.", context); } return contentType + ";charset=utf-8"; } /** * Returns value of the custom 'format' URL parameter. */ function getCustomFormat(context) { var queryParameters = context.uriTree.queryParameters; if (queryParameters) { return queryParameters[CUSTOM_FORMAT_PARAMETER]; } } function serializePropertyValue(dbSeg) { if (dbSeg.sql.rows.length > 1) { throw new InternalError('To many rows for serializing a property'); } var property = dbSeg.singleProperty; var converter; converter = dbSeg.entityType.__metadata.converterMapToXMLPayload[property]; return converter(dbSeg.sql.rows[0][property]); } function serializeCountValue(context, dbSeg) { context.logger.silly('resourceprocessor', 'serializeCountValue'); if (dbSeg.sql.rows.length > 1) { throw new InternalError('To many rows for serializing a $count response'); } return dbSeg.sql.rows[0].c; }