UNPKG

@softchef/cdk-iot-device-management

Version:

IoT device management is composed of things, thing types, thing groups, jobs, files API services. The constructs can be used independently, that are based on full-managed service to create an API Gateway & Lambda function.

144 lines (143 loc) 6.65 kB
import { __assign, __values } from "tslib"; import { HttpResponse } from "@aws-sdk/protocol-http"; import { buildQueryString } from "@aws-sdk/querystring-builder"; import { connect, constants } from "http2"; import { getTransformedHeaders } from "./get-transformed-headers"; import { writeRequestBody } from "./write-request-body"; var NodeHttp2Handler = (function () { function NodeHttp2Handler(_a) { var _b = _a === void 0 ? {} : _a, requestTimeout = _b.requestTimeout, sessionTimeout = _b.sessionTimeout, disableConcurrentStreams = _b.disableConcurrentStreams; this.metadata = { handlerProtocol: "h2" }; this.requestTimeout = requestTimeout; this.sessionTimeout = sessionTimeout; this.disableConcurrentStreams = disableConcurrentStreams; this.sessionCache = new Map(); } NodeHttp2Handler.prototype.destroy = function () { var e_1, _a; var _this = this; try { for (var _b = __values(this.sessionCache.values()), _c = _b.next(); !_c.done; _c = _b.next()) { var sessions = _c.value; sessions.forEach(function (session) { return _this.destroySession(session); }); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } this.sessionCache.clear(); }; NodeHttp2Handler.prototype.handle = function (request, _a) { var _this = this; var _b = _a === void 0 ? {} : _a, abortSignal = _b.abortSignal; return new Promise(function (resolve, rejectOriginal) { var _a; var fulfilled = false; if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) { fulfilled = true; var abortError = new Error("Request aborted"); abortError.name = "AbortError"; rejectOriginal(abortError); return; } var hostname = request.hostname, method = request.method, port = request.port, protocol = request.protocol, path = request.path, query = request.query; var authority = protocol + "//" + hostname + (port ? ":" + port : ""); var session = _this.getSession(authority, _this.disableConcurrentStreams || false); var reject = function (err) { if (_this.disableConcurrentStreams) { _this.destroySession(session); } fulfilled = true; rejectOriginal(err); }; var queryString = buildQueryString(query || {}); var req = session.request(__assign(__assign({}, request.headers), (_a = {}, _a[constants.HTTP2_HEADER_PATH] = queryString ? path + "?" + queryString : path, _a[constants.HTTP2_HEADER_METHOD] = method, _a))); req.on("response", function (headers) { var httpResponse = new HttpResponse({ statusCode: headers[":status"] || -1, headers: getTransformedHeaders(headers), body: req, }); fulfilled = true; resolve({ response: httpResponse }); if (_this.disableConcurrentStreams) { session.close(); _this.deleteSessionFromCache(authority, session); } }); var requestTimeout = _this.requestTimeout; if (requestTimeout) { req.setTimeout(requestTimeout, function () { req.close(); var timeoutError = new Error("Stream timed out because of no activity for " + requestTimeout + " ms"); timeoutError.name = "TimeoutError"; reject(timeoutError); }); } if (abortSignal) { abortSignal.onabort = function () { req.close(); var abortError = new Error("Request aborted"); abortError.name = "AbortError"; reject(abortError); }; } req.on("frameError", function (type, code, id) { reject(new Error("Frame type id " + type + " in stream id " + id + " has failed with code " + code + ".")); }); req.on("error", reject); req.on("aborted", function () { reject(new Error("HTTP/2 stream is abnormally aborted in mid-communication with result code " + req.rstCode + ".")); }); req.on("close", function () { if (_this.disableConcurrentStreams) { session.destroy(); } if (!fulfilled) { reject(new Error("Unexpected error: http2 request did not get a response")); } }); writeRequestBody(req, request); }); }; NodeHttp2Handler.prototype.getSession = function (authority, disableConcurrentStreams) { var _this = this; var sessionCache = this.sessionCache; var existingSessions = sessionCache.get(authority) || []; if (existingSessions.length > 0 && !disableConcurrentStreams) return existingSessions[0]; var newSession = connect(authority); var destroySessionCb = function () { _this.destroySession(newSession); _this.deleteSessionFromCache(authority, newSession); }; newSession.on("goaway", destroySessionCb); newSession.on("error", destroySessionCb); newSession.on("frameError", destroySessionCb); var sessionTimeout = this.sessionTimeout; if (sessionTimeout) { newSession.setTimeout(sessionTimeout, destroySessionCb); } existingSessions.push(newSession); sessionCache.set(authority, existingSessions); return newSession; }; NodeHttp2Handler.prototype.destroySession = function (session) { if (!session.destroyed) { session.destroy(); } }; NodeHttp2Handler.prototype.deleteSessionFromCache = function (authority, session) { var existingSessions = this.sessionCache.get(authority) || []; if (!existingSessions.includes(session)) { return; } this.sessionCache.set(authority, existingSessions.filter(function (s) { return s !== session; })); }; return NodeHttp2Handler; }()); export { NodeHttp2Handler };