UNPKG

open-next-cdk

Version:

Deploy a NextJS app using OpenNext packaging to serverless AWS using CDK

160 lines (159 loc) 6.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NodeHttp2Handler = void 0; const protocol_http_1 = require("@smithy/protocol-http"); const querystring_builder_1 = require("@smithy/querystring-builder"); const http2_1 = require("http2"); const get_transformed_headers_1 = require("./get-transformed-headers"); const node_http2_connection_manager_1 = require("./node-http2-connection-manager"); const write_request_body_1 = require("./write-request-body"); class NodeHttp2Handler { constructor(options) { this.metadata = { handlerProtocol: "h2" }; this.connectionManager = new node_http2_connection_manager_1.NodeHttp2ConnectionManager({}); this.configProvider = new Promise((resolve, reject) => { if (typeof options === "function") { options() .then((opts) => { resolve(opts || {}); }) .catch(reject); } else { resolve(options || {}); } }); } destroy() { this.connectionManager.destroy(); } async handle(request, { abortSignal } = {}) { if (!this.config) { this.config = await this.configProvider; this.connectionManager.setDisableConcurrentStreams(this.config.disableConcurrentStreams || false); if (this.config.maxConcurrentStreams) { this.connectionManager.setMaxConcurrentStreams(this.config.maxConcurrentStreams); } } const { requestTimeout, disableConcurrentStreams } = this.config; return new Promise((_resolve, _reject) => { var _a, _b, _c; let fulfilled = false; let writeRequestBodyPromise = undefined; const resolve = async (arg) => { await writeRequestBodyPromise; _resolve(arg); }; const reject = async (arg) => { await writeRequestBodyPromise; _reject(arg); }; if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) { fulfilled = true; const abortError = new Error("Request aborted"); abortError.name = "AbortError"; reject(abortError); return; } const { hostname, method, port, protocol, query } = request; let auth = ""; if (request.username != null || request.password != null) { const username = (_a = request.username) !== null && _a !== void 0 ? _a : ""; const password = (_b = request.password) !== null && _b !== void 0 ? _b : ""; auth = `${username}:${password}@`; } const authority = `${protocol}//${auth}${hostname}${port ? `:${port}` : ""}`; const requestContext = { destination: new URL(authority) }; const session = this.connectionManager.lease(requestContext, { requestTimeout: (_c = this.config) === null || _c === void 0 ? void 0 : _c.sessionTimeout, disableConcurrentStreams: disableConcurrentStreams || false, }); const rejectWithDestroy = (err) => { if (disableConcurrentStreams) { this.destroySession(session); } fulfilled = true; reject(err); }; const queryString = (0, querystring_builder_1.buildQueryString)(query || {}); let path = request.path; if (queryString) { path += `?${queryString}`; } if (request.fragment) { path += `#${request.fragment}`; } const req = session.request({ ...request.headers, [http2_1.constants.HTTP2_HEADER_PATH]: path, [http2_1.constants.HTTP2_HEADER_METHOD]: method, }); session.ref(); req.on("response", (headers) => { const httpResponse = new protocol_http_1.HttpResponse({ statusCode: headers[":status"] || -1, headers: (0, get_transformed_headers_1.getTransformedHeaders)(headers), body: req, }); fulfilled = true; resolve({ response: httpResponse }); if (disableConcurrentStreams) { session.close(); this.connectionManager.deleteSession(authority, session); } }); if (requestTimeout) { req.setTimeout(requestTimeout, () => { req.close(); const timeoutError = new Error(`Stream timed out because of no activity for ${requestTimeout} ms`); timeoutError.name = "TimeoutError"; rejectWithDestroy(timeoutError); }); } if (abortSignal) { abortSignal.onabort = () => { req.close(); const abortError = new Error("Request aborted"); abortError.name = "AbortError"; rejectWithDestroy(abortError); }; } req.on("frameError", (type, code, id) => { rejectWithDestroy(new Error(`Frame type id ${type} in stream id ${id} has failed with code ${code}.`)); }); req.on("error", rejectWithDestroy); req.on("aborted", () => { rejectWithDestroy(new Error(`HTTP/2 stream is abnormally aborted in mid-communication with result code ${req.rstCode}.`)); }); req.on("close", () => { session.unref(); if (disableConcurrentStreams) { session.destroy(); } if (!fulfilled) { rejectWithDestroy(new Error("Unexpected error: http2 request did not get a response")); } }); writeRequestBodyPromise = (0, write_request_body_1.writeRequestBody)(req, request, requestTimeout); }); } updateHttpClientConfig(key, value) { this.config = undefined; this.configProvider = this.configProvider.then((config) => { return { ...config, [key]: value, }; }); } httpHandlerConfigs() { var _a; return (_a = this.config) !== null && _a !== void 0 ? _a : {}; } destroySession(session) { if (!session.destroyed) { session.destroy(); } } } exports.NodeHttp2Handler = NodeHttp2Handler;