UNPKG

@scloud/lambda-api

Version:

Lambda handler for API Gateway proxy requests

80 lines 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.apiHandler = apiHandler; const helpers_1 = require("./helpers"); function textResponse(statusCode, body) { return { statusCode, headers: { 'Content-Type': 'text/plain' }, body }; } /** * API route handler */ async function apiHandler(event, context, routes = { '/api/ping': { GET: async (request) => ({ statusCode: 200, body: request }) }, }, errorHandler = async (request) => ({ statusCode: 500, body: { error: `Internal server error: ${request.path}` } }), catchAll = async (request) => textResponse(404, `Not found: ${request.path}`), contextBuilder) { console.log(`Executing ${context.functionName} version: ${process.env.COMMIT_HASH}`); const request = (0, helpers_1.parseRequest)(event); let response; try { const match = (0, helpers_1.matchRoute)(routes, request.path); if (!match.route) { // Catch-all / 404 response = await catchAll(request); } else { const handlerFunction = match.route[request.method]; // Handle the request: if (handlerFunction) { if (contextBuilder) await contextBuilder(request); response = await handlerFunction({ ...request, pathParameters: match.params }); } else { response = textResponse(405, 'Method not allowed'); } } } catch (e) { // Fallback error handling console.error(`${e.message}\n${e.stack}`); response = textResponse(500, `Internal server error: ${request.path}`); try { // Error handling if (errorHandler) response = await errorHandler(request, e); } catch (ee) { console.error(`Error in error handler: ${ee.message}\n${ee.stack}`); } } // API Gateway Proxy result let body = ''; if (typeof response.body === 'string') { // Use the body as-is // Potentially add a text/plain content type header: response.headers = { 'Content-Type': 'text/plain', ...response.headers }; body = response.body; } else if (response.body) { // Stringify the response object // API Gateway returns application/json by default body = JSON.stringify(response.body); } const result = { statusCode: response.statusCode, body, headers: response.headers, }; // Cookies (if set) const cookieHeaders = (0, helpers_1.buildCookie)(response.cookies); if (cookieHeaders) { result.multiValueHeaders = { 'Set-Cookie': cookieHeaders, }; } return result; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBc0JBLGdDQXFFQztBQWxGRCx1Q0FBa0U7QUFFbEUsU0FBUyxZQUFZLENBQUMsVUFBa0IsRUFBRSxJQUFZO0lBQ3BELE9BQU87UUFDTCxVQUFVO1FBQ1YsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBRTtRQUN6QyxJQUFJO0tBQ0wsQ0FBQztBQUNKLENBQUM7QUFFRDs7R0FFRztBQUNJLEtBQUssVUFBVSxVQUFVLENBQzlCLEtBQTJCLEVBQzNCLE9BQWdCLEVBQ2hCLFNBQWlCO0lBQ2YsV0FBVyxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxPQUFnQixFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRTtDQUN2RixFQUNELGVBQWtFLEtBQUssRUFBRSxPQUFnQixFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsMEJBQTBCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFDOUssV0FBb0IsS0FBSyxFQUFFLE9BQWdCLEVBQUUsRUFBRSxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsY0FBYyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsRUFDL0YsY0FBK0I7SUFFL0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLE9BQU8sQ0FBQyxZQUFZLGFBQWEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ3JGLE1BQU0sT0FBTyxHQUFHLElBQUEsc0JBQVksRUFBQyxLQUFLLENBQUMsQ0FBQztJQUVwQyxJQUFJLFFBQWtCLENBQUM7SUFDdkIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxLQUFLLEdBQUcsSUFBQSxvQkFBVSxFQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDL0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNqQixrQkFBa0I7WUFDbEIsUUFBUSxHQUFHLE1BQU0sUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3JDLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBcUIsQ0FBQyxDQUFDO1lBRW5FLHNCQUFzQjtZQUN0QixJQUFJLGVBQWUsRUFBRSxDQUFDO2dCQUNwQixJQUFJLGNBQWM7b0JBQUUsTUFBTSxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2xELFFBQVEsR0FBRyxNQUFNLGVBQWUsQ0FBQyxFQUFFLEdBQUcsT0FBTyxFQUFFLGNBQWMsRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUNqRixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sUUFBUSxHQUFHLFlBQVksQ0FBQyxHQUFHLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztZQUNyRCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsMEJBQTBCO1FBQzFCLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBSSxDQUFXLENBQUMsT0FBTyxLQUFNLENBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLFFBQVEsR0FBRyxZQUFZLENBQUMsR0FBRyxFQUFFLDBCQUEwQixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN2RSxJQUFJLENBQUM7WUFDSCxpQkFBaUI7WUFDakIsSUFBSSxZQUFZO2dCQUFFLFFBQVEsR0FBRyxNQUFNLFlBQVksQ0FBQyxPQUFPLEVBQUUsQ0FBVSxDQUFDLENBQUM7UUFDdkUsQ0FBQztRQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDWixPQUFPLENBQUMsS0FBSyxDQUFDLDJCQUE0QixFQUFZLENBQUMsT0FBTyxLQUFNLEVBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQzVGLENBQUM7SUFDSCxDQUFDO0lBRUQsMkJBQTJCO0lBQzNCLElBQUksSUFBSSxHQUFXLEVBQUUsQ0FBQztJQUN0QixJQUFJLE9BQU8sUUFBUSxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUN0QyxxQkFBcUI7UUFDckIsb0RBQW9EO1FBQ3BELFFBQVEsQ0FBQyxPQUFPLEdBQUcsRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFLEdBQUcsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3pFLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO0lBQ3ZCLENBQUM7U0FBTSxJQUFJLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN6QixnQ0FBZ0M7UUFDaEMsa0RBQWtEO1FBQ2xELElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBQ0QsTUFBTSxNQUFNLEdBQTBCO1FBQ3BDLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVTtRQUMvQixJQUFJO1FBQ0osT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPO0tBQzFCLENBQUM7SUFFRixtQkFBbUI7SUFDbkIsTUFBTSxhQUFhLEdBQUcsSUFBQSxxQkFBVyxFQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNwRCxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sQ0FBQyxpQkFBaUIsR0FBRztZQUN6QixZQUFZLEVBQUUsYUFBYTtTQUM1QixDQUFDO0lBQ0osQ0FBQztJQUVELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBUElHYXRld2F5UHJveHlFdmVudCxcbiAgQVBJR2F0ZXdheVByb3h5UmVzdWx0LFxuICBDb250ZXh0LFxufSBmcm9tICdhd3MtbGFtYmRhJztcbmltcG9ydCB7XG4gIENvbnRleHRCdWlsZGVyLFxuICBIYW5kbGVyLCBSZXF1ZXN0LCBSZXNwb25zZSwgUm91dGUsIFJvdXRlcyxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBidWlsZENvb2tpZSwgbWF0Y2hSb3V0ZSwgcGFyc2VSZXF1ZXN0IH0gZnJvbSAnLi9oZWxwZXJzJztcblxuZnVuY3Rpb24gdGV4dFJlc3BvbnNlKHN0YXR1c0NvZGU6IG51bWJlciwgYm9keTogc3RyaW5nKTogUmVzcG9uc2Uge1xuICByZXR1cm4ge1xuICAgIHN0YXR1c0NvZGUsXG4gICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ3RleHQvcGxhaW4nIH0sXG4gICAgYm9keVxuICB9O1xufVxuXG4vKipcbiAqIEFQSSByb3V0ZSBoYW5kbGVyXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcGlIYW5kbGVyKFxuICBldmVudDogQVBJR2F0ZXdheVByb3h5RXZlbnQsXG4gIGNvbnRleHQ6IENvbnRleHQsXG4gIHJvdXRlczogUm91dGVzID0ge1xuICAgICcvYXBpL3BpbmcnOiB7IEdFVDogYXN5bmMgKHJlcXVlc3Q6IFJlcXVlc3QpID0+ICh7IHN0YXR1c0NvZGU6IDIwMCwgYm9keTogcmVxdWVzdCB9KSB9LFxuICB9LFxuICBlcnJvckhhbmRsZXI6IChyZXF1ZXN0OiBSZXF1ZXN0LCBlOiBFcnJvcikgPT4gUHJvbWlzZTxSZXNwb25zZT4gPSBhc3luYyAocmVxdWVzdDogUmVxdWVzdCkgPT4gKHsgc3RhdHVzQ29kZTogNTAwLCBib2R5OiB7IGVycm9yOiBgSW50ZXJuYWwgc2VydmVyIGVycm9yOiAke3JlcXVlc3QucGF0aH1gIH0gfSksXG4gIGNhdGNoQWxsOiBIYW5kbGVyID0gYXN5bmMgKHJlcXVlc3Q6IFJlcXVlc3QpID0+IHRleHRSZXNwb25zZSg0MDQsIGBOb3QgZm91bmQ6ICR7cmVxdWVzdC5wYXRofWApLFxuICBjb250ZXh0QnVpbGRlcj86IENvbnRleHRCdWlsZGVyLFxuKTogUHJvbWlzZTxBUElHYXRld2F5UHJveHlSZXN1bHQ+IHtcbiAgY29uc29sZS5sb2coYEV4ZWN1dGluZyAke2NvbnRleHQuZnVuY3Rpb25OYW1lfSB2ZXJzaW9uOiAke3Byb2Nlc3MuZW52LkNPTU1JVF9IQVNIfWApO1xuICBjb25zdCByZXF1ZXN0ID0gcGFyc2VSZXF1ZXN0KGV2ZW50KTtcblxuICBsZXQgcmVzcG9uc2U6IFJlc3BvbnNlO1xuICB0cnkge1xuICAgIGNvbnN0IG1hdGNoID0gbWF0Y2hSb3V0ZShyb3V0ZXMsIHJlcXVlc3QucGF0aCk7XG4gICAgaWYgKCFtYXRjaC5yb3V0ZSkge1xuICAgICAgLy8gQ2F0Y2gtYWxsIC8gNDA0XG4gICAgICByZXNwb25zZSA9IGF3YWl0IGNhdGNoQWxsKHJlcXVlc3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBoYW5kbGVyRnVuY3Rpb24gPSBtYXRjaC5yb3V0ZVtyZXF1ZXN0Lm1ldGhvZCBhcyBrZXlvZiBSb3V0ZV07XG5cbiAgICAgIC8vIEhhbmRsZSB0aGUgcmVxdWVzdDpcbiAgICAgIGlmIChoYW5kbGVyRnVuY3Rpb24pIHtcbiAgICAgICAgaWYgKGNvbnRleHRCdWlsZGVyKSBhd2FpdCBjb250ZXh0QnVpbGRlcihyZXF1ZXN0KTtcbiAgICAgICAgcmVzcG9uc2UgPSBhd2FpdCBoYW5kbGVyRnVuY3Rpb24oeyAuLi5yZXF1ZXN0LCBwYXRoUGFyYW1ldGVyczogbWF0Y2gucGFyYW1zIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzcG9uc2UgPSB0ZXh0UmVzcG9uc2UoNDA1LCAnTWV0aG9kIG5vdCBhbGxvd2VkJyk7XG4gICAgICB9XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgLy8gRmFsbGJhY2sgZXJyb3IgaGFuZGxpbmdcbiAgICBjb25zb2xlLmVycm9yKGAkeyhlIGFzIEVycm9yKS5tZXNzYWdlfVxcbiR7KGUgYXMgRXJyb3IpLnN0YWNrfWApO1xuICAgIHJlc3BvbnNlID0gdGV4dFJlc3BvbnNlKDUwMCwgYEludGVybmFsIHNlcnZlciBlcnJvcjogJHtyZXF1ZXN0LnBhdGh9YCk7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEVycm9yIGhhbmRsaW5nXG4gICAgICBpZiAoZXJyb3JIYW5kbGVyKSByZXNwb25zZSA9IGF3YWl0IGVycm9ySGFuZGxlcihyZXF1ZXN0LCBlIGFzIEVycm9yKTtcbiAgICB9IGNhdGNoIChlZSkge1xuICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgaW4gZXJyb3IgaGFuZGxlcjogJHsoZWUgYXMgRXJyb3IpLm1lc3NhZ2V9XFxuJHsoZWUgYXMgRXJyb3IpLnN0YWNrfWApO1xuICAgIH1cbiAgfVxuXG4gIC8vIEFQSSBHYXRld2F5IFByb3h5IHJlc3VsdFxuICBsZXQgYm9keTogc3RyaW5nID0gJyc7XG4gIGlmICh0eXBlb2YgcmVzcG9uc2UuYm9keSA9PT0gJ3N0cmluZycpIHtcbiAgICAvLyBVc2UgdGhlIGJvZHkgYXMtaXNcbiAgICAvLyBQb3RlbnRpYWxseSBhZGQgYSB0ZXh0L3BsYWluIGNvbnRlbnQgdHlwZSBoZWFkZXI6XG4gICAgcmVzcG9uc2UuaGVhZGVycyA9IHsgJ0NvbnRlbnQtVHlwZSc6ICd0ZXh0L3BsYWluJywgLi4ucmVzcG9uc2UuaGVhZGVycyB9O1xuICAgIGJvZHkgPSByZXNwb25zZS5ib2R5O1xuICB9IGVsc2UgaWYgKHJlc3BvbnNlLmJvZHkpIHtcbiAgICAvLyBTdHJpbmdpZnkgdGhlIHJlc3BvbnNlIG9iamVjdFxuICAgIC8vIEFQSSBHYXRld2F5IHJldHVybnMgYXBwbGljYXRpb24vanNvbiBieSBkZWZhdWx0XG4gICAgYm9keSA9IEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlLmJvZHkpO1xuICB9XG4gIGNvbnN0IHJlc3VsdDogQVBJR2F0ZXdheVByb3h5UmVzdWx0ID0ge1xuICAgIHN0YXR1c0NvZGU6IHJlc3BvbnNlLnN0YXR1c0NvZGUsXG4gICAgYm9keSxcbiAgICBoZWFkZXJzOiByZXNwb25zZS5oZWFkZXJzLFxuICB9O1xuXG4gIC8vIENvb2tpZXMgKGlmIHNldClcbiAgY29uc3QgY29va2llSGVhZGVycyA9IGJ1aWxkQ29va2llKHJlc3BvbnNlLmNvb2tpZXMpO1xuICBpZiAoY29va2llSGVhZGVycykge1xuICAgIHJlc3VsdC5tdWx0aVZhbHVlSGVhZGVycyA9IHtcbiAgICAgICdTZXQtQ29va2llJzogY29va2llSGVhZGVycyxcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cbiJdfQ==