azurite
Version:
An open source Azure Storage API compatible server
194 lines • 9.35 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.getUTF8ByteSize = exports.isEtagValid = exports.newHighPrecisionTimeStamp = exports.newTableEntityEtag = exports.validateTableName = exports.getPayloadFormat = exports.getTimestampString = exports.checkApiVersion = exports.getOdataAnnotations = exports.updateEntityOdataAnnotationsForResponse = exports.getEntityOdataAnnotationsForResponse = exports.getEntityOdataAnnotationsForRequest = exports.updateTableOptionalOdataAnnotationsForResponse = exports.getTablePropertiesOdataAnnotationsForResponse = exports.updateTableOdataAnnotationsForResponse = exports.getTableOdataAnnotationsForResponse = exports.getTableOdataAnnotationsForRequest = void 0;
const tslib_1 = require("tslib");
const utils_1 = require("../../common/utils/utils");
const StorageErrorFactory_1 = tslib_1.__importDefault(require("../errors/StorageErrorFactory"));
const constants_1 = require("./constants");
function getTableOdataAnnotationsForRequest(account, table) {
return getOdataAnnotations(account, "", table);
}
exports.getTableOdataAnnotationsForRequest = getTableOdataAnnotationsForRequest;
function getTableOdataAnnotationsForResponse(account, table, urlPrefix) {
return getOdataAnnotations(account, urlPrefix, table);
}
exports.getTableOdataAnnotationsForResponse = getTableOdataAnnotationsForResponse;
function updateTableOdataAnnotationsForResponse(table, account, urlPrefix, accept) {
const annotation = getTableOdataAnnotationsForResponse(account, table.table, urlPrefix);
if (accept &&
(accept === constants_1.MINIMAL_METADATA_ACCEPT || accept === constants_1.FULL_METADATA_ACCEPT)) {
table.odatametadata = annotation.odatametadata;
}
if (accept && accept === constants_1.FULL_METADATA_ACCEPT) {
table.odatatype = annotation.odatatype;
table.odataid = annotation.odataid;
table.odataeditLink = annotation.odataeditLink;
}
return table;
}
exports.updateTableOdataAnnotationsForResponse = updateTableOdataAnnotationsForResponse;
function getTablePropertiesOdataAnnotationsForResponse(tableName, account, urlPrefix, accept) {
const table = {
tableName
};
const annotation = getTableOdataAnnotationsForResponse(account, tableName, urlPrefix);
if (accept && accept === constants_1.FULL_METADATA_ACCEPT) {
table.odatatype = annotation.odatatype;
table.odataid = annotation.odataid;
table.odataeditLink = annotation.odataeditLink;
}
return table;
}
exports.getTablePropertiesOdataAnnotationsForResponse = getTablePropertiesOdataAnnotationsForResponse;
function updateTableOptionalOdataAnnotationsForResponse(tableLike, account, table, urlPrefix, accept) {
const annotation = getTableOdataAnnotationsForResponse(account, table, urlPrefix);
if (accept &&
(accept === constants_1.MINIMAL_METADATA_ACCEPT || accept === constants_1.FULL_METADATA_ACCEPT)) {
tableLike.odatametadata = annotation.odatametadata;
}
if (accept && accept === constants_1.FULL_METADATA_ACCEPT) {
tableLike.odatatype = annotation.odatatype;
tableLike.odataid = annotation.odataid;
tableLike.odataeditLink = annotation.odataeditLink;
}
return tableLike;
}
exports.updateTableOptionalOdataAnnotationsForResponse = updateTableOptionalOdataAnnotationsForResponse;
function getEntityOdataAnnotationsForRequest(account, table, partitionKey, rowKey) {
return getOdataAnnotations(account, "", table, partitionKey, rowKey);
}
exports.getEntityOdataAnnotationsForRequest = getEntityOdataAnnotationsForRequest;
function getEntityOdataAnnotationsForResponse(account, table, urlPrefix, partitionKey, rowKey, accept) {
const annotation = getOdataAnnotations(account, urlPrefix, table, partitionKey, rowKey);
const response = {};
if (accept &&
(accept === constants_1.MINIMAL_METADATA_ACCEPT || accept === constants_1.FULL_METADATA_ACCEPT)) {
response.odatametadata = annotation.odatametadata;
}
if (accept && accept === constants_1.FULL_METADATA_ACCEPT) {
response.odatatype = annotation.odatatype;
response.odataid = annotation.odataid;
response.odataeditLink = annotation.odataeditLink;
}
return response;
}
exports.getEntityOdataAnnotationsForResponse = getEntityOdataAnnotationsForResponse;
function updateEntityOdataAnnotationsForResponse(entity, account, table, urlPrefix, accept) {
const annotation = getOdataAnnotations(account, table, urlPrefix, entity.PartitionKey, entity.RowKey);
if (accept &&
(accept === constants_1.MINIMAL_METADATA_ACCEPT || accept === constants_1.FULL_METADATA_ACCEPT)) {
entity.odatametadata = annotation.odatametadata;
}
if (accept && accept === constants_1.FULL_METADATA_ACCEPT) {
entity.odatatype = annotation.odatatype;
entity.odataid = annotation.odataid;
entity.odataeditLink = annotation.odataeditLink;
}
return entity;
}
exports.updateEntityOdataAnnotationsForResponse = updateEntityOdataAnnotationsForResponse;
// table service APIs are in layers
// we need to ensure that table, entity, and service
// API layers are not affected when we change this odata response.
// check that change does not impact query entities & query tables
function getOdataAnnotations(account, urlPrefix, table, partitionKey, rowKey) {
const urlPrefixEndWithSlash = urlPrefix.endsWith("/")
? urlPrefix
: `${urlPrefix}/`;
if (typeof partitionKey === "string" && partitionKey.length > 0) {
if (typeof rowKey !== "string" || partitionKey.length === 0) {
throw TypeError("PartitionKey and RowKey must provide at the same time.");
}
return {
odatametadata: `${urlPrefixEndWithSlash}$metadata#${table}/@Element`,
odatatype: `${account}.${table}`,
odataid: `${urlPrefixEndWithSlash}${table}(PartitionKey='${partitionKey}',RowKey='${rowKey}')`,
odataeditLink: `${table}(PartitionKey='${partitionKey}',RowKey='${rowKey}')`
};
}
else {
return {
odatametadata: `${urlPrefixEndWithSlash}$metadata#Tables${table ? "/@Element" : ""}`,
odatatype: `${account}.Tables`,
odataid: `${urlPrefixEndWithSlash}Tables('${table}')`,
odataeditLink: `Tables('${table}')`
};
}
}
exports.getOdataAnnotations = getOdataAnnotations;
function checkApiVersion(inputApiVersion, validApiVersions, context) {
if (!validApiVersions.includes(inputApiVersion)) {
throw StorageErrorFactory_1.default.getInvalidAPIVersion(context, inputApiVersion);
}
}
exports.checkApiVersion = checkApiVersion;
function getTimestampString(date) {
return date.toISOString().replace("Z", "0000Z");
}
exports.getTimestampString = getTimestampString;
function getPayloadFormat(context) {
let format = context.request?.getHeader(constants_1.HeaderConstants.ACCEPT);
const formatParameter = context.request?.getQuery("$format");
if (typeof formatParameter === "string") {
format = formatParameter;
}
if (format === undefined || format === "") {
format = constants_1.XML_METADATA;
}
if (format === "application/json") {
format = constants_1.MINIMAL_METADATA_ACCEPT;
}
format = format.replace(/\s/g, "");
return format;
}
exports.getPayloadFormat = getPayloadFormat;
// https://docs.microsoft.com/en-us/rest/api/storageservices/understanding-the-table-service-data-model#table-names
function validateTableName(context, tableName) {
if (tableName !== "" && (tableName.length < 3 || tableName.length > 63)) {
throw StorageErrorFactory_1.default.getOutOfRangeName(context);
}
const reg = new RegExp("^[A-Za-z][A-Za-z0-9]{2,62}$");
if (!reg.test(tableName) && !tableName.startsWith("$Metric")) {
throw StorageErrorFactory_1.default.getInvalidResourceName(context);
}
if (tableName.toLowerCase() === "tables") {
throw StorageErrorFactory_1.default.getInvalidResourceName(context);
}
}
exports.validateTableName = validateTableName;
function newTableEntityEtag(highPresModTime) {
// Etag as returned by Table Storage should match W/"datetime'<ISO8601datetime>'"
// as we need the same value for last Modification time, we now only accept a string here
return "W/\"datetime'" + encodeURIComponent(highPresModTime) + "'\"";
}
exports.newTableEntityEtag = newTableEntityEtag;
function newHighPrecisionTimeStamp(startTime) {
return (0, utils_1.truncatedISO8061Date)(startTime, true, true);
}
exports.newHighPrecisionTimeStamp = newHighPrecisionTimeStamp;
/**
* Checks if an eTag is valid
*
* @export
* @param {string} etag
* @return {*} {boolean}
*/
function isEtagValid(etag) {
// Weak etag is required. This is parity with Azure and legacy emulator.
// Source for regex: https://stackoverflow.com/a/11572348
const match = etag.match(/^[wW]\/"([^"]|\\")*"$/);
return match === null;
}
exports.isEtagValid = isEtagValid;
/**
* Get the byte size of a string in UTF8.
*
* @public
* @param {Date} requestDate
* @returns {string}
*/
function getUTF8ByteSize(text) {
return Buffer.from(text, "utf8").length;
}
exports.getUTF8ByteSize = getUTF8ByteSize;
//# sourceMappingURL=utils.js.map
;