@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
JavaScript
;
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;
}