UNPKG

@scaffoldly/serverless-util

Version:
191 lines 7.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.snsEventResponseMapper = exports.dynamoDBStreamEventResponseMapper = exports.snsEventRequestMapper = exports.snsExtractTopicName = exports.dynamoDBStreamEventRequestMapper = exports.extractRequestToken = exports.extractToken = exports.extractAuthorization = exports.constructServiceUrl = exports.assertProcessUuid = void 0; const auth_1 = require("./auth"); const constants_1 = require("./constants"); const db_1 = require("./db"); const errors_1 = require("./errors"); const assertProcessUuid = (actual, expected = constants_1.PROCESS_UUID) => { if (!actual) { throw new Error('Missing Process UUID: actual is undefined'); } if (!expected) { throw new Error('Missing Process UUID: expected is undefined'); } if (!actual.toLowerCase) { throw new Error('Missing Process UUID: actual.toLowerCase is undefined'); } if (!expected.toLowerCase) { throw new Error('Missing Process UUID: expected.toLowerCase is undefined'); } if (actual.toLowerCase() === expected.toLowerCase()) { return true; } throw new Error(`Provided process UUID (${actual}) does not match expected process UUID`); }; exports.assertProcessUuid = assertProcessUuid; const constructServiceUrl = (request, serviceSlug, path) => { const { headers } = request; const { host } = headers; const ssl = headers['x-forwarded-proto'] === 'https'; let slug = serviceSlug ? `/${serviceSlug}` : ''; let actualPath = path || ''; if (!actualPath.startsWith('/') && actualPath.length !== 0) { actualPath = `/${actualPath}`; } return `${ssl ? 'https' : 'http'}://${host}${slug}${actualPath}`; }; exports.constructServiceUrl = constructServiceUrl; const extractAuthorization = (request) => { if (!request) { console.warn('Unable to extract authorization header: Request is null'); return null; } const { headers } = request; if (!headers) { console.warn('Unable to extract authorization header: No headers'); return null; } const { authorization } = headers; if (authorization) { return authorization; } const { Authorization } = headers; if (Authorization) { return Authorization; } console.warn("Missing header named 'Authorization' or 'authorization'"); return null; }; exports.extractAuthorization = extractAuthorization; const extractToken = (authorization, authTypes = auth_1.AUTH_PREFIXES) => { if (!authorization) { console.warn('Missing authorization header'); return null; } let token = authorization; const parts = token.split(' '); if (parts.length > 2) { console.warn('Malformed authorization header: Extra spaces'); return null; } if (parts.length === 2) { const prefix = parts[0]; authTypes = authTypes.map((t) => t.toLowerCase()); if (authTypes.indexOf(prefix.toLowerCase()) === -1) { console.warn(`Invalid token type: ${prefix}`); return null; } [, token] = parts; } return token; }; exports.extractToken = extractToken; const extractRequestToken = (request) => { const authorization = exports.extractAuthorization(request); if (!authorization) { throw new errors_1.HttpError(401, 'Unauthorized'); } const token = exports.extractToken(authorization); if (!token) { throw new errors_1.HttpError(401, 'Unauthorized'); } return token; }; exports.extractRequestToken = extractRequestToken; const dynamoDBStreamEventRequestMapper = (path, id = constants_1.PROCESS_UUID) => { return (container) => { const body = { Records: container.event.Records.reduce((acc, record) => { if (!record.dynamodb || !record.eventID || !record.eventName || !record.eventSourceARN || !record.awsRegion) { return acc; } const tableName = db_1.dynamoDBStreamEventExtractTableName(record.eventSourceARN); if (!tableName) { return acc; } acc.push({ dynamodb: { Keys: record.dynamodb.Keys ? db_1.unmarshallDynamoDBImage(record.dynamodb.Keys) : undefined, New: record.dynamodb.NewImage ? db_1.unmarshallDynamoDBImage(record.dynamodb.NewImage) : undefined, Old: record.dynamodb.OldImage ? db_1.unmarshallDynamoDBImage(record.dynamodb.OldImage) : undefined, }, eventID: record.eventID, eventName: record.eventName, eventSourceARN: record.eventSourceARN, awsRegion: record.awsRegion, tableName, }); return acc; }, []), }; return { hostname: 'dynamodb.amazonaws.com', method: 'POST', path, headers: { [constants_1.PROCESS_UUID_HEADER]: id, [constants_1.MAPPED_EVENT_HEADER]: constants_1.MAPPED_EVENT_DYNAMODB_STREAM, }, body, }; }; }; exports.dynamoDBStreamEventRequestMapper = dynamoDBStreamEventRequestMapper; const snsExtractTopicName = (topicArn) => { // TODO Proper ARN Parser if (!topicArn) { return; } const parts = topicArn.split(':'); if (parts.length !== 6) { return; } return parts[5]; }; exports.snsExtractTopicName = snsExtractTopicName; const snsEventRequestMapper = (path, id = constants_1.PROCESS_UUID) => { return (container) => { const body = { Records: container.event.Records.reduce((acc, record) => { const topicName = exports.snsExtractTopicName(record.Sns.TopicArn); if (!topicName) { return acc; } // TODO Verify Signature let obj = undefined; try { obj = JSON.parse(record.Sns.Message); } catch (e) { console.warn('Unable to parse message into JSON'); } acc.push({ ...record, Sns: { ...record.Sns, Subject: record.Sns.Subject || '', Object: obj, TopicName: topicName, }, }); return acc; }, []), }; return { hostname: 'sns.amazonaws.com', method: 'POST', path, headers: { [constants_1.PROCESS_UUID_HEADER]: id, [constants_1.MAPPED_EVENT_HEADER]: constants_1.MAPPED_EVENT_SNS, }, body, }; }; }; exports.snsEventRequestMapper = snsEventRequestMapper; const emptyResponseMapper = () => () => { }; exports.dynamoDBStreamEventResponseMapper = emptyResponseMapper; exports.snsEventResponseMapper = emptyResponseMapper; //# sourceMappingURL=http.js.map