UNPKG

azurite

Version:

An open source Azure Storage API compatible server

140 lines 7.18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractStoragePartsFromPath = exports.queueStorageContextMiddleware = void 0; const tslib_1 = require("tslib"); const v4_1 = tslib_1.__importDefault(require("uuid/v4")); const Logger_1 = tslib_1.__importDefault(require("../../common/Logger")); const constants_1 = require("../../common/utils/constants"); const constants_2 = require("../../common/utils/constants"); const QueueStorageContext_1 = tslib_1.__importDefault(require("../context/QueueStorageContext")); const StorageErrorFactory_1 = tslib_1.__importDefault(require("../errors/StorageErrorFactory")); const constants_3 = require("../utils/constants"); const utils_1 = require("../utils/utils"); function createQueueStorageContextMiddleware(skipApiVersionCheck, disableProductStyleUrl) { return (req, res, next) => { return queueStorageContextMiddleware(req, res, next, skipApiVersionCheck, disableProductStyleUrl); }; } exports.default = createQueueStorageContextMiddleware; /** * A middleware extract related queue service context. * * @export * @param {Request} req An express compatible Request object * @param {Response} res An express compatible Response object * @param {NextFunction} next An express middleware next callback */ function queueStorageContextMiddleware(req, res, next, skipApiVersionCheck, disableProductStyleUrl) { // Set server header in every Azurite response res.setHeader(constants_3.HeaderConstants.SERVER, `Azurite-Queue/${constants_3.VERSION}`); const requestID = (0, v4_1.default)(); if (!skipApiVersionCheck) { const apiVersion = req.header(constants_3.HeaderConstants.X_MS_VERSION); if (apiVersion !== undefined) { (0, utils_1.checkApiVersion)(apiVersion, constants_3.ValidAPIVersions, requestID); } } const queueContext = new QueueStorageContext_1.default(res.locals, constants_3.DEFAULT_QUEUE_CONTEXT_PATH); queueContext.startTime = new Date(); queueContext.xMsRequestID = requestID; Logger_1.default.info(`QueueStorageContextMiddleware: RequestMethod=${req.method} RequestURL=${req.protocol}://${req.hostname}${req.url} RequestHeaders:${JSON.stringify(req.headers)} ClientIP=${req.ip} Protocol=${req.protocol} HTTPVersion=${req.httpVersion}`, requestID); const [account, queue, message, messageId, isSecondary] = extractStoragePartsFromPath(req.hostname, req.path, disableProductStyleUrl); queueContext.account = account; queueContext.queue = queue; queueContext.message = message; queueContext.messageId = messageId; queueContext.isSecondary = isSecondary; // Emulator's URL pattern is like http://hostname[:port]/account/queue/messages // (or, alternatively, http[s]://account.localhost[:port]/queue/messages) // Create a router to exclude account name from req.path, as url path in swagger doesn't include account // Exclude account name from req.path for dispatchMiddleware queueContext.dispatchPattern = queue !== undefined ? message !== undefined ? messageId !== undefined ? `/queue/messages/messageId` : `/queue/messages` : `/queue` : "/"; // The value of queue may be "" in some cases, e.g. list queue with .../accountname/?comp=list... if (req.query && (req.query.restype === "service" || req.query.comp === "list")) { queueContext.dispatchPattern = "/"; } queueContext.authenticationPath = req.path; if (isSecondary) { const pos = queueContext.authenticationPath.search(constants_3.SECONDARY_SUFFIX); if (pos !== -1) { queueContext.authenticationPath = queueContext.authenticationPath.substr(0, pos) + queueContext.authenticationPath.substr(pos + constants_3.SECONDARY_SUFFIX.length); } } if (account === undefined) { const handlerError = StorageErrorFactory_1.default.getInvalidQueryParameterValue(requestID); Logger_1.default.error(`QueueStorageContextMiddleware: QueueStorageContextMiddleware: ${handlerError.message}`, requestID); return next(handlerError); } // If it is not and account operations, then the queue name should be validated. if (queueContext.dispatchPattern !== "/" && queue !== undefined) { const nameValidateStatus = (0, utils_1.isValidName)(queue); if (nameValidateStatus === utils_1.nameValidateCode.invalidUri) { const handlerError = StorageErrorFactory_1.default.getInvalidUri(requestID, { UriPath: `/${queue}` }); return next(handlerError); } if (nameValidateStatus === utils_1.nameValidateCode.outOfRange) { const handlerError = StorageErrorFactory_1.default.getOutOfRangeName(requestID); return next(handlerError); } if (nameValidateStatus === utils_1.nameValidateCode.invalidName) { const handlerError = StorageErrorFactory_1.default.getInvalidResourceName(requestID); return next(handlerError); } } Logger_1.default.info(`QueueStorageContextMiddleware: Account=${account} Queue=${queue} Message=${message} MessageId=${messageId}`, requestID); next(); } exports.queueStorageContextMiddleware = queueStorageContextMiddleware; /** * Extract storage account, queue, and massages from URL path. * * @param {string} path * @returns {([string | undefined, string | undefined, string | undefined, boolean | undefined])} */ function extractStoragePartsFromPath(hostname, path, disableProductStyleUrl) { let account; let queue; let message; let messageId; let isSecondary = false; const decodedPath = decodeURIComponent(path); const normalizedPath = decodedPath.startsWith("/") ? decodedPath.substr(1) : decodedPath; // Remove starting "/" const parts = normalizedPath.split("/"); let urlPartIndex = 0; const isIPAddress = constants_1.IP_REGEX.test(hostname); const isNoAccountHostName = constants_2.NO_ACCOUNT_HOST_NAMES.has(hostname.toLowerCase()); const firstDotIndex = hostname.indexOf("."); // If hostname is not an IP address or a known host name, and has a dot inside, // we assume user wants to access emulator with a production-like URL. if (!disableProductStyleUrl && !isIPAddress && !isNoAccountHostName && firstDotIndex > 0) { account = hostname.substring(0, firstDotIndex); } else { account = parts[urlPartIndex++]; } queue = parts[urlPartIndex++]; // For delete and update, it is messages/messageid?popreceipt=string-value message = parts[urlPartIndex++]; messageId = parts[urlPartIndex++]; if (account.endsWith(constants_3.SECONDARY_SUFFIX)) { account = account.substr(0, account.length - constants_3.SECONDARY_SUFFIX.length); isSecondary = true; } return [account, queue, message, messageId, isSecondary]; } exports.extractStoragePartsFromPath = extractStoragePartsFromPath; //# sourceMappingURL=queueStorageContext.middleware.js.map