Socket
Socket
Sign inDemoInstall

@aws-sdk/node-http-handler

Package Overview
Dependencies
Maintainers
7
Versions
140
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@aws-sdk/node-http-handler - npm Package Compare versions

Comparing version 3.20.0 to 3.21.0

11

CHANGELOG.md

@@ -6,2 +6,13 @@ # Change Log

# [3.21.0](https://github.com/aws/aws-sdk-js-v3/compare/v3.20.0...v3.21.0) (2021-07-09)
### Features
* **node-http-handler:** configure disableConcurrentStreams in NodeHttp2Handler ([#2553](https://github.com/aws/aws-sdk-js-v3/issues/2553)) ([9303bf7](https://github.com/aws/aws-sdk-js-v3/commit/9303bf7cccbfca1ac7b81d15728d03b5757e5805))
# [3.20.0](https://github.com/aws/aws-sdk-js-v3/compare/v3.19.0...v3.20.0) (2021-07-02)

@@ -8,0 +19,0 @@

101

dist/cjs/node-http2-handler.js

@@ -10,14 +10,14 @@ "use strict";

class NodeHttp2Handler {
constructor({ requestTimeout, sessionTimeout } = {}) {
constructor({ requestTimeout, sessionTimeout, disableConcurrentStreams } = {}) {
this.metadata = { handlerProtocol: "h2" };
this.requestTimeout = requestTimeout;
this.sessionTimeout = sessionTimeout;
this.connectionPool = new Map();
this.disableConcurrentStreams = disableConcurrentStreams;
this.sessionCache = new Map();
}
destroy() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_, http2Session] of this.connectionPool) {
http2Session.destroy();
for (const sessions of this.sessionCache.values()) {
sessions.forEach((session) => this.destroySession(session));
}
this.connectionPool.clear();
this.sessionCache.clear();
}

@@ -29,17 +29,23 @@ handle(request, { abortSignal } = {}) {

let fulfilled = false;
const reject = (err) => {
fulfilled = true;
rejectOriginal(err);
};
// if the request was already aborted, prevent doing extra work
if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) {
fulfilled = true;
const abortError = new Error("Request aborted");
abortError.name = "AbortError";
reject(abortError);
rejectOriginal(abortError);
return;
}
const { hostname, method, port, protocol, path, query } = request;
const authority = `${protocol}//${hostname}${port ? `:${port}` : ""}`;
const session = this.getSession(authority, this.disableConcurrentStreams || false);
const reject = (err) => {
if (this.disableConcurrentStreams) {
this.destroySession(session);
}
fulfilled = true;
rejectOriginal(err);
};
const queryString = querystring_builder_1.buildQueryString(query || {});
// create the http2 request
const req = this.getSession(`${protocol}//${hostname}${port ? `:${port}` : ""}`).request({
const req = session.request({
...request.headers,

@@ -57,2 +63,8 @@ [http2_1.constants.HTTP2_HEADER_PATH]: queryString ? `${path}?${queryString}` : path,

resolve({ response: httpResponse });
if (this.disableConcurrentStreams) {
// Gracefully closes the Http2Session, allowing any existing streams to complete
// on their own and preventing new Http2Stream instances from being created.
session.close();
this.deleteSessionFromCache(authority, session);
}
});

@@ -85,2 +97,5 @@ const requestTimeout = this.requestTimeout;

req.on("close", () => {
if (this.disableConcurrentStreams) {
session.destroy();
}
if (!fulfilled) {

@@ -93,11 +108,19 @@ reject(new Error("Unexpected error: http2 request did not get a response"));

}
getSession(authority) {
const connectionPool = this.connectionPool;
const existingSession = connectionPool.get(authority);
if (existingSession)
return existingSession;
/**
* Returns a session for the given URL.
*
* @param authority The URL to create a session for.
* @param disableConcurrentStreams If true, a new session will be created for each request.
* @returns A session for the given URL.
*/
getSession(authority, disableConcurrentStreams) {
const sessionCache = this.sessionCache;
const existingSessions = sessionCache.get(authority) || [];
// If concurrent streams are not disabled, we can use the existing session.
if (existingSessions.length > 0 && !disableConcurrentStreams)
return existingSessions[0];
const newSession = http2_1.connect(authority);
connectionPool.set(authority, newSession);
const destroySessionCb = () => {
this.destroySession(authority, newSession);
this.destroySession(newSession);
this.deleteSessionFromCache(authority, newSession);
};

@@ -109,26 +132,13 @@ newSession.on("goaway", destroySessionCb);

if (sessionTimeout) {
newSession.setTimeout(sessionTimeout, () => {
if (connectionPool.get(authority) === newSession) {
newSession.close();
connectionPool.delete(authority);
}
});
newSession.setTimeout(sessionTimeout, destroySessionCb);
}
existingSessions.push(newSession);
sessionCache.set(authority, existingSessions);
return newSession;
}
/**
* Destroy a session immediately and remove it from the http2 pool.
*
* This check ensures that the session is only closed once
* and that an event on one session does not close a different session.
* Destroys a session.
* @param session The session to destroy.
*/
destroySession(authority, session) {
if (this.connectionPool.get(authority) !== session) {
// Already closed?
return;
}
this.connectionPool.delete(authority);
session.removeAllListeners("goaway");
session.removeAllListeners("error");
session.removeAllListeners("frameError");
destroySession(session) {
if (!session.destroyed) {

@@ -138,4 +148,17 @@ session.destroy();

}
/**
* Delete a session from the connection pool.
* @param authority The authority of the session to delete.
* @param session The session to delete.
*/
deleteSessionFromCache(authority, session) {
const existingSessions = this.sessionCache.get(authority) || [];
if (!existingSessions.includes(session)) {
// If the session is not in the cache, it has already been deleted.
return;
}
this.sessionCache.set(authority, existingSessions.filter((s) => s !== session));
}
}
exports.NodeHttp2Handler = NodeHttp2Handler;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1odHRwMi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL25vZGUtaHR0cDItaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwREFBZ0Y7QUFDaEYsc0VBQWdFO0FBRWhFLGlDQUErRDtBQUUvRCx1RUFBa0U7QUFDbEUsNkRBQXdEO0FBb0J4RCxNQUFhLGdCQUFnQjtJQU0zQixZQUFZLEVBQUUsY0FBYyxFQUFFLGNBQWMsS0FBOEIsRUFBRTtRQUY1RCxhQUFRLEdBQUcsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFHbkQsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLEdBQUcsRUFBOEIsQ0FBQztJQUM5RCxDQUFDO0lBRUQsT0FBTztRQUNMLDZEQUE2RDtRQUM3RCxLQUFLLE1BQU0sQ0FBQyxDQUFDLEVBQUUsWUFBWSxDQUFDLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUNuRCxZQUFZLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDeEI7UUFDRCxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRCxNQUFNLENBQUMsT0FBb0IsRUFBRSxFQUFFLFdBQVcsS0FBeUIsRUFBRTtRQUNuRSxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLGNBQWMsRUFBRSxFQUFFO1lBQzdDLHdGQUF3RjtZQUN4RiwrRUFBK0U7WUFDL0UsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDO1lBQ3RCLE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBVSxFQUFFLEVBQUU7Z0JBQzVCLFNBQVMsR0FBRyxJQUFJLENBQUM7Z0JBQ2pCLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN0QixDQUFDLENBQUM7WUFDRiwrREFBK0Q7WUFD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aEQsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNuQixjQUFjLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2lCQUNsQztZQUNILENBQUMsQ0FBQyxDQUFDO1NBQ0o7UUFDRCxPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxjQUFjLENBQUMsU0FBaUIsRUFBRSxPQUEyQjtRQUNuRSxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLE9BQU8sRUFBRTtZQUNsRCxrQkFBa0I7WUFDbEIsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdEMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNwQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUU7WUFDdEIsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQ25CO0lBQ0gsQ0FBQztDQUNGO0FBM0lELDRDQTJJQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBIYW5kbGVyLCBIdHRwUmVxdWVzdCwgSHR0cFJlc3BvbnNlIH0gZnJvbSBcIkBhd3Mtc2RrL3Byb3RvY29sLWh0dHBcIjtcbmltcG9ydCB7IGJ1aWxkUXVlcnlTdHJpbmcgfSBmcm9tIFwiQGF3cy1zZGsvcXVlcnlzdHJpbmctYnVpbGRlclwiO1xuaW1wb3J0IHsgSHR0cEhhbmRsZXJPcHRpb25zIH0gZnJvbSBcIkBhd3Mtc2RrL3R5cGVzXCI7XG5pbXBvcnQgeyBDbGllbnRIdHRwMlNlc3Npb24sIGNvbm5lY3QsIGNvbnN0YW50cyB9IGZyb20gXCJodHRwMlwiO1xuXG5pbXBvcnQgeyBnZXRUcmFuc2Zvcm1lZEhlYWRlcnMgfSBmcm9tIFwiLi9nZXQtdHJhbnNmb3JtZWQtaGVhZGVyc1wiO1xuaW1wb3J0IHsgd3JpdGVSZXF1ZXN0Qm9keSB9IGZyb20gXCIuL3dyaXRlLXJlcXVlc3QtYm9keVwiO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIGh0dHAyIG9wdGlvbnMgdGhhdCBjYW4gYmUgcGFzc2VkIHRvIGEgbm9kZSBodHRwMiBjbGllbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZUh0dHAySGFuZGxlck9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIG1heGltdW0gdGltZSBpbiBtaWxsaXNlY29uZHMgdGhhdCBhIHN0cmVhbSBtYXkgcmVtYWluIGlkbGUgYmVmb3JlIGl0XG4gICAqIGlzIGNsb3NlZC5cbiAgICovXG4gIHJlcXVlc3RUaW1lb3V0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSB0aW1lIGluIG1pbGxpc2Vjb25kcyB0aGF0IGEgc2Vzc2lvbiBvciBzb2NrZXQgbWF5IHJlbWFpbiBpZGxlXG4gICAqIGJlZm9yZSBpdCBpcyBjbG9zZWQuXG4gICAqIGh0dHBzOi8vbm9kZWpzLm9yZy9kb2NzL2xhdGVzdC12MTIueC9hcGkvaHR0cDIuaHRtbCNodHRwMl9odHRwMnNlc3Npb25fYW5kX3NvY2tldHNcbiAgICovXG4gIHNlc3Npb25UaW1lb3V0PzogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgTm9kZUh0dHAySGFuZGxlciBpbXBsZW1lbnRzIEh0dHBIYW5kbGVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSByZXF1ZXN0VGltZW91dD86IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBzZXNzaW9uVGltZW91dD86IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBjb25uZWN0aW9uUG9vbDogTWFwPHN0cmluZywgQ2xpZW50SHR0cDJTZXNzaW9uPjtcbiAgcHVibGljIHJlYWRvbmx5IG1ldGFkYXRhID0geyBoYW5kbGVyUHJvdG9jb2w6IFwiaDJcIiB9O1xuXG4gIGNvbnN0cnVjdG9yKHsgcmVxdWVzdFRpbWVvdXQsIHNlc3Npb25UaW1lb3V0IH06IE5vZGVIdHRwMkhhbmRsZXJPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLnJlcXVlc3RUaW1lb3V0ID0gcmVxdWVzdFRpbWVvdXQ7XG4gICAgdGhpcy5zZXNzaW9uVGltZW91dCA9IHNlc3Npb25UaW1lb3V0O1xuICAgIHRoaXMuY29ubmVjdGlvblBvb2wgPSBuZXcgTWFwPHN0cmluZywgQ2xpZW50SHR0cDJTZXNzaW9uPigpO1xuICB9XG5cbiAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgZm9yIChjb25zdCBbXywgaHR0cDJTZXNzaW9uXSBvZiB0aGlzLmNvbm5lY3Rpb25Qb29sKSB7XG4gICAgICBodHRwMlNlc3Npb24uZGVzdHJveSgpO1xuICAgIH1cbiAgICB0aGlzLmNvbm5lY3Rpb25Qb29sLmNsZWFyKCk7XG4gIH1cblxuICBoYW5kbGUocmVxdWVzdDogSHR0cFJlcXVlc3QsIHsgYWJvcnRTaWduYWwgfTogSHR0cEhhbmRsZXJPcHRpb25zID0ge30pOiBQcm9taXNlPHsgcmVzcG9uc2U6IEh0dHBSZXNwb25zZSB9PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3RPcmlnaW5hbCkgPT4ge1xuICAgICAgLy8gSXQncyByZWR1bmRhbnQgdG8gdHJhY2sgZnVsZmlsbGVkIGJlY2F1c2UgcHJvbWlzZXMgdXNlIHRoZSBmaXJzdCByZXNvbHV0aW9uL3JlamVjdGlvblxuICAgICAgLy8gYnV0IGF2b2lkcyBnZW5lcmF0aW5nIHVubmVjZXNzYXJ5IHN0YWNrIHRyYWNlcyBpbiB0aGUgXCJjbG9zZVwiIGV2ZW50IGhhbmRsZXIuXG4gICAgICBsZXQgZnVsZmlsbGVkID0gZmFsc2U7XG4gICAgICBjb25zdCByZWplY3QgPSAoZXJyOiBFcnJvcikgPT4ge1xuICAgICAgICBmdWxmaWxsZWQgPSB0cnVlO1xuICAgICAgICByZWplY3RPcmlnaW5hbChlcnIpO1xuICAgICAgfTtcbiAgICAgIC8vIGlmIHRoZSByZXF1ZXN0IHdhcyBhbHJlYWR5IGFib3J0ZWQsIHByZXZlbnQgZG9pbmcgZXh0cmEgd29ya1xuICAgICAgaWYgKGFib3J0U2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgICAgIGNvbnN0IGFib3J0RXJyb3IgPSBuZXcgRXJyb3IoXCJSZXF1ZXN0IGFib3J0ZWRcIik7XG4gICAgICAgIGFib3J0RXJyb3IubmFtZSA9IFwiQWJvcnRFcnJvclwiO1xuICAgICAgICByZWplY3QoYWJvcnRFcnJvcik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBob3N0bmFtZSwgbWV0aG9kLCBwb3J0LCBwcm90b2NvbCwgcGF0aCwgcXVlcnkgfSA9IHJlcXVlc3Q7XG4gICAgICBjb25zdCBxdWVyeVN0cmluZyA9IGJ1aWxkUXVlcnlTdHJpbmcocXVlcnkgfHwge30pO1xuXG4gICAgICAvLyBjcmVhdGUgdGhlIGh0dHAyIHJlcXVlc3RcbiAgICAgIGNvbnN0IHJlcSA9IHRoaXMuZ2V0U2Vzc2lvbihgJHtwcm90b2NvbH0vLyR7aG9zdG5hbWV9JHtwb3J0ID8gYDoke3BvcnR9YCA6IFwiXCJ9YCkucmVxdWVzdCh7XG4gICAgICAgIC4uLnJlcXVlc3QuaGVhZGVycyxcbiAgICAgICAgW2NvbnN0YW50cy5IVFRQMl9IRUFERVJfUEFUSF06IHF1ZXJ5U3RyaW5nID8gYCR7cGF0aH0/JHtxdWVyeVN0cmluZ31gIDogcGF0aCxcbiAgICAgICAgW2NvbnN0YW50cy5IVFRQMl9IRUFERVJfTUVUSE9EXTogbWV0aG9kLFxuICAgICAgfSk7XG5cbiAgICAgIHJlcS5vbihcInJlc3BvbnNlXCIsIChoZWFkZXJzKSA9PiB7XG4gICAgICAgIGNvbnN0IGh0dHBSZXNwb25zZSA9IG5ldyBIdHRwUmVzcG9uc2Uoe1xuICAgICAgICAgIHN0YXR1c0NvZGU6IGhlYWRlcnNbXCI6c3RhdHVzXCJdIHx8IC0xLFxuICAgICAgICAgIGhlYWRlcnM6IGdldFRyYW5zZm9ybWVkSGVhZGVycyhoZWFkZXJzKSxcbiAgICAgICAgICBib2R5OiByZXEsXG4gICAgICAgIH0pO1xuICAgICAgICBmdWxmaWxsZWQgPSB0cnVlO1xuICAgICAgICByZXNvbHZlKHsgcmVzcG9uc2U6IGh0dHBSZXNwb25zZSB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXF1ZXN0VGltZW91dCA9IHRoaXMucmVxdWVzdFRpbWVvdXQ7XG4gICAgICBpZiAocmVxdWVzdFRpbWVvdXQpIHtcbiAgICAgICAgcmVxLnNldFRpbWVvdXQocmVxdWVzdFRpbWVvdXQsICgpID0+IHtcbiAgICAgICAgICByZXEuY2xvc2UoKTtcbiAgICAgICAgICBjb25zdCB0aW1lb3V0RXJyb3IgPSBuZXcgRXJyb3IoYFN0cmVhbSB0aW1lZCBvdXQgYmVjYXVzZSBvZiBubyBhY3Rpdml0eSBmb3IgJHtyZXF1ZXN0VGltZW91dH0gbXNgKTtcbiAgICAgICAgICB0aW1lb3V0RXJyb3IubmFtZSA9IFwiVGltZW91dEVycm9yXCI7XG4gICAgICAgICAgcmVqZWN0KHRpbWVvdXRFcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoYWJvcnRTaWduYWwpIHtcbiAgICAgICAgYWJvcnRTaWduYWwub25hYm9ydCA9ICgpID0+IHtcbiAgICAgICAgICByZXEuY2xvc2UoKTtcbiAgICAgICAgICBjb25zdCBhYm9ydEVycm9yID0gbmV3IEVycm9yKFwiUmVxdWVzdCBhYm9ydGVkXCIpO1xuICAgICAgICAgIGFib3J0RXJyb3IubmFtZSA9IFwiQWJvcnRFcnJvclwiO1xuICAgICAgICAgIHJlamVjdChhYm9ydEVycm9yKTtcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgLy8gU2V0IHVwIGhhbmRsZXJzIGZvciBlcnJvcnNcbiAgICAgIHJlcS5vbihcImZyYW1lRXJyb3JcIiwgcmVqZWN0KTtcbiAgICAgIHJlcS5vbihcImVycm9yXCIsIHJlamVjdCk7XG4gICAgICByZXEub24oXCJnb2F3YXlcIiwgcmVqZWN0KTtcbiAgICAgIHJlcS5vbihcImFib3J0ZWRcIiwgcmVqZWN0KTtcblxuICAgICAgLy8gVGhlIEhUVFAvMiBlcnJvciBjb2RlIHVzZWQgd2hlbiBjbG9zaW5nIHRoZSBzdHJlYW0gY2FuIGJlIHJldHJpZXZlZCB1c2luZyB0aGVcbiAgICAgIC8vIGh0dHAyc3RyZWFtLnJzdENvZGUgcHJvcGVydHkuIElmIHRoZSBjb2RlIGlzIGFueSB2YWx1ZSBvdGhlciB0aGFuIE5HSFRUUDJfTk9fRVJST1IgKDApLFxuICAgICAgLy8gYW4gJ2Vycm9yJyBldmVudCB3aWxsIGhhdmUgYWxzbyBiZWVuIGVtaXR0ZWQuXG4gICAgICByZXEub24oXCJjbG9zZVwiLCAoKSA9PiB7XG4gICAgICAgIGlmICghZnVsZmlsbGVkKSB7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIlVuZXhwZWN0ZWQgZXJyb3I6IGh0dHAyIHJlcXVlc3QgZGlkIG5vdCBnZXQgYSByZXNwb25zZVwiKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgd3JpdGVSZXF1ZXN0Qm9keShyZXEsIHJlcXVlc3QpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTZXNzaW9uKGF1dGhvcml0eTogc3RyaW5nKTogQ2xpZW50SHR0cDJTZXNzaW9uIHtcbiAgICBjb25zdCBjb25uZWN0aW9uUG9vbCA9IHRoaXMuY29ubmVjdGlvblBvb2w7XG4gICAgY29uc3QgZXhpc3RpbmdTZXNzaW9uID0gY29ubmVjdGlvblBvb2wuZ2V0KGF1dGhvcml0eSk7XG4gICAgaWYgKGV4aXN0aW5nU2Vzc2lvbikgcmV0dXJuIGV4aXN0aW5nU2Vzc2lvbjtcblxuICAgIGNvbnN0IG5ld1Nlc3Npb24gPSBjb25uZWN0KGF1dGhvcml0eSk7XG4gICAgY29ubmVjdGlvblBvb2wuc2V0KGF1dGhvcml0eSwgbmV3U2Vzc2lvbik7XG4gICAgY29uc3QgZGVzdHJveVNlc3Npb25DYiA9ICgpID0+IHtcbiAgICAgIHRoaXMuZGVzdHJveVNlc3Npb24oYXV0aG9yaXR5LCBuZXdTZXNzaW9uKTtcbiAgICB9O1xuICAgIG5ld1Nlc3Npb24ub24oXCJnb2F3YXlcIiwgZGVzdHJveVNlc3Npb25DYik7XG4gICAgbmV3U2Vzc2lvbi5vbihcImVycm9yXCIsIGRlc3Ryb3lTZXNzaW9uQ2IpO1xuICAgIG5ld1Nlc3Npb24ub24oXCJmcmFtZUVycm9yXCIsIGRlc3Ryb3lTZXNzaW9uQ2IpO1xuXG4gICAgY29uc3Qgc2Vzc2lvblRpbWVvdXQgPSB0aGlzLnNlc3Npb25UaW1lb3V0O1xuICAgIGlmIChzZXNzaW9uVGltZW91dCkge1xuICAgICAgbmV3U2Vzc2lvbi5zZXRUaW1lb3V0KHNlc3Npb25UaW1lb3V0LCAoKSA9PiB7XG4gICAgICAgIGlmIChjb25uZWN0aW9uUG9vbC5nZXQoYXV0aG9yaXR5KSA9PT0gbmV3U2Vzc2lvbikge1xuICAgICAgICAgIG5ld1Nlc3Npb24uY2xvc2UoKTtcbiAgICAgICAgICBjb25uZWN0aW9uUG9vbC5kZWxldGUoYXV0aG9yaXR5KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBuZXdTZXNzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIERlc3Ryb3kgYSBzZXNzaW9uIGltbWVkaWF0ZWx5IGFuZCByZW1vdmUgaXQgZnJvbSB0aGUgaHR0cDIgcG9vbC5cbiAgICpcbiAgICogVGhpcyBjaGVjayBlbnN1cmVzIHRoYXQgdGhlIHNlc3Npb24gaXMgb25seSBjbG9zZWQgb25jZVxuICAgKiBhbmQgdGhhdCBhbiBldmVudCBvbiBvbmUgc2Vzc2lvbiBkb2VzIG5vdCBjbG9zZSBhIGRpZmZlcmVudCBzZXNzaW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBkZXN0cm95U2Vzc2lvbihhdXRob3JpdHk6IHN0cmluZywgc2Vzc2lvbjogQ2xpZW50SHR0cDJTZXNzaW9uKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY29ubmVjdGlvblBvb2wuZ2V0KGF1dGhvcml0eSkgIT09IHNlc3Npb24pIHtcbiAgICAgIC8vIEFscmVhZHkgY2xvc2VkP1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmNvbm5lY3Rpb25Qb29sLmRlbGV0ZShhdXRob3JpdHkpO1xuICAgIHNlc3Npb24ucmVtb3ZlQWxsTGlzdGVuZXJzKFwiZ29hd2F5XCIpO1xuICAgIHNlc3Npb24ucmVtb3ZlQWxsTGlzdGVuZXJzKFwiZXJyb3JcIik7XG4gICAgc2Vzc2lvbi5yZW1vdmVBbGxMaXN0ZW5lcnMoXCJmcmFtZUVycm9yXCIpO1xuICAgIGlmICghc2Vzc2lvbi5kZXN0cm95ZWQpIHtcbiAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgIH1cbiAgfVxufVxuIl19
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1odHRwMi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL25vZGUtaHR0cDItaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwREFBZ0Y7QUFDaEYsc0VBQWdFO0FBRWhFLGlDQUErRDtBQUUvRCx1RUFBa0U7QUFDbEUsNkRBQXdEO0FBNEJ4RCxNQUFhLGdCQUFnQjtJQVEzQixZQUFZLEVBQUUsY0FBYyxFQUFFLGNBQWMsRUFBRSx3QkFBd0IsS0FBOEIsRUFBRTtRQUh0RixhQUFRLEdBQUcsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFJbkQsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLHdCQUF3QixHQUFHLHdCQUF3QixDQUFDO1FBQ3pELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQWdDLENBQUM7SUFDOUQsQ0FBQztJQUVELE9BQU87UUFDTCxLQUFLLE1BQU0sUUFBUSxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDakQsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1NBQzdEO1FBQ0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRUQsTUFBTSxDQUFDLE9BQW9CLEVBQUUsRUFBRSxXQUFXLEtBQXlCLEVBQUU7UUFDbkUsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxjQUFjLEVBQUUsRUFBRTtZQUM3Qyx3RkFBd0Y7WUFDeEYsK0VBQStFO1lBQy9FLElBQUksU0FBUyxHQUFHLEtBQUssQ0FBQztZQUV0QiwrREFBK0Q7WUFDL0QsSUFBSSxXQUFXLGFBQVgsV0FB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QVksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2hFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDdkMsbUVBQW1FO1lBQ25FLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUNuQixTQUFTLEVBQ1QsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssT0FBTyxDQUFDLENBQzlDLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUE5S0QsNENBOEtDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSHR0cEhhbmRsZXIsIEh0dHBSZXF1ZXN0LCBIdHRwUmVzcG9uc2UgfSBmcm9tIFwiQGF3cy1zZGsvcHJvdG9jb2wtaHR0cFwiO1xuaW1wb3J0IHsgYnVpbGRRdWVyeVN0cmluZyB9IGZyb20gXCJAYXdzLXNkay9xdWVyeXN0cmluZy1idWlsZGVyXCI7XG5pbXBvcnQgeyBIdHRwSGFuZGxlck9wdGlvbnMgfSBmcm9tIFwiQGF3cy1zZGsvdHlwZXNcIjtcbmltcG9ydCB7IENsaWVudEh0dHAyU2Vzc2lvbiwgY29ubmVjdCwgY29uc3RhbnRzIH0gZnJvbSBcImh0dHAyXCI7XG5cbmltcG9ydCB7IGdldFRyYW5zZm9ybWVkSGVhZGVycyB9IGZyb20gXCIuL2dldC10cmFuc2Zvcm1lZC1oZWFkZXJzXCI7XG5pbXBvcnQgeyB3cml0ZVJlcXVlc3RCb2R5IH0gZnJvbSBcIi4vd3JpdGUtcmVxdWVzdC1ib2R5XCI7XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgaHR0cDIgb3B0aW9ucyB0aGF0IGNhbiBiZSBwYXNzZWQgdG8gYSBub2RlIGh0dHAyIGNsaWVudC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBOb2RlSHR0cDJIYW5kbGVyT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSB0aW1lIGluIG1pbGxpc2Vjb25kcyB0aGF0IGEgc3RyZWFtIG1heSByZW1haW4gaWRsZSBiZWZvcmUgaXRcbiAgICogaXMgY2xvc2VkLlxuICAgKi9cbiAgcmVxdWVzdFRpbWVvdXQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRoYXQgYSBzZXNzaW9uIG9yIHNvY2tldCBtYXkgcmVtYWluIGlkbGVcbiAgICogYmVmb3JlIGl0IGlzIGNsb3NlZC5cbiAgICogaHR0cHM6Ly9ub2RlanMub3JnL2RvY3MvbGF0ZXN0LXYxMi54L2FwaS9odHRwMi5odG1sI2h0dHAyX2h0dHAyc2Vzc2lvbl9hbmRfc29ja2V0c1xuICAgKi9cbiAgc2Vzc2lvblRpbWVvdXQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIERpc2FibGVzIHByb2Nlc3NpbmcgY29uY3VycmVudCBzdHJlYW1zIG9uIGEgQ2xpZW50SHR0cDJTZXNzaW9uIGluc3RhbmNlLiBXaGVuIHNldFxuICAgKiB0byB0cnVlLCB0aGUgaGFuZGxlciB3aWxsIGNyZWF0ZSBhIG5ldyBzZXNzaW9uIGluc3RhbmNlIGZvciBlYWNoIHJlcXVlc3QgdG8gYSBVUkwuXG4gICAqICoqRGVmYXVsdDoqKiBmYWxzZS5cbiAgICogaHR0cHM6Ly9ub2RlanMub3JnL2FwaS9odHRwMi5odG1sI2h0dHAyX2NsYXNzX2NsaWVudGh0dHAyc2Vzc2lvblxuICAgKi9cbiAgZGlzYWJsZUNvbmN1cnJlbnRTdHJlYW1zPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIE5vZGVIdHRwMkhhbmRsZXIgaW1wbGVtZW50cyBIdHRwSGFuZGxlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVxdWVzdFRpbWVvdXQ/OiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2Vzc2lvblRpbWVvdXQ/OiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGlzYWJsZUNvbmN1cnJlbnRTdHJlYW1zPzogYm9vbGVhbjtcblxuICBwdWJsaWMgcmVhZG9ubHkgbWV0YWRhdGEgPSB7IGhhbmRsZXJQcm90b2NvbDogXCJoMlwiIH07XG4gIHByaXZhdGUgc2Vzc2lvbkNhY2hlOiBNYXA8c3RyaW5nLCBDbGllbnRIdHRwMlNlc3Npb25bXT47XG5cbiAgY29uc3RydWN0b3IoeyByZXF1ZXN0VGltZW91dCwgc2Vzc2lvblRpbWVvdXQsIGRpc2FibGVDb25jdXJyZW50U3RyZWFtcyB9OiBOb2RlSHR0cDJIYW5kbGVyT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5yZXF1ZXN0VGltZW91dCA9IHJlcXVlc3RUaW1lb3V0O1xuICAgIHRoaXMuc2Vzc2lvblRpbWVvdXQgPSBzZXNzaW9uVGltZW91dDtcbiAgICB0aGlzLmRpc2FibGVDb25jdXJyZW50U3RyZWFtcyA9IGRpc2FibGVDb25jdXJyZW50U3RyZWFtcztcbiAgICB0aGlzLnNlc3Npb25DYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBDbGllbnRIdHRwMlNlc3Npb25bXT4oKTtcbiAgfVxuXG4gIGRlc3Ryb3koKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBzZXNzaW9ucyBvZiB0aGlzLnNlc3Npb25DYWNoZS52YWx1ZXMoKSkge1xuICAgICAgc2Vzc2lvbnMuZm9yRWFjaCgoc2Vzc2lvbikgPT4gdGhpcy5kZXN0cm95U2Vzc2lvbihzZXNzaW9uKSk7XG4gICAgfVxuICAgIHRoaXMuc2Vzc2lvbkNhY2hlLmNsZWFyKCk7XG4gIH1cblxuICBoYW5kbGUocmVxdWVzdDogSHR0cFJlcXVlc3QsIHsgYWJvcnRTaWduYWwgfTogSHR0cEhhbmRsZXJPcHRpb25zID0ge30pOiBQcm9taXNlPHsgcmVzcG9uc2U6IEh0dHBSZXNwb25zZSB9PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3RPcmlnaW5hbCkgPT4ge1xuICAgICAgLy8gSXQncyByZWR1bmRhbnQgdG8gdHJhY2sgZnVsZmlsbGVkIGJlY2F1c2UgcHJvbWlzZXMgdXNlIHRoZSBmaXJzdCByZXNvbHV0aW9uL3JlamVjdGlvblxuICAgICAgLy8gYnV0IGF2b2lkcyBnZW5lcmF0aW5nIHVubmVjZXNzYXJ5IHN0YWNrIHRyYWNlcyBpbiB0aGUgXCJjbG9zZVwiIGV2ZW50IGhhbmRsZXIuXG4gICAgICBsZXQgZnVsZmlsbGVkID0gZmFsc2U7XG5cbiAgICAgIC8vIGlmIHRoZSByZXF1ZXN0IHdhcyBhbHJlYWR5IGFib3J0ZWQsIHByZXZlbnQgZG9pbmcgZXh0cmEgd29ya1xuICAgICAgaWYgKGFib3J0U2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgICAgIGZ1bGZpbGxlZCA9IHRydWU7XG4gICAgICAgIGNvbnN0IGFib3J0RXJyb3IgPSBuZXcgRXJyb3IoXCJSZXF1ZXN0IGFib3J0ZWRcIik7XG4gICAgICAgIGFib3J0RXJyb3IubmFtZSA9IFwiQWJvcnRFcnJvclwiO1xuICAgICAgICByZWplY3RPcmlnaW5hbChhYm9ydEVycm9yKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7IGhvc3RuYW1lLCBtZXRob2QsIHBvcnQsIHByb3RvY29sLCBwYXRoLCBxdWVyeSB9ID0gcmVxdWVzdDtcbiAgICAgIGNvbnN0IGF1dGhvcml0eSA9IGAke3Byb3RvY29sfS8vJHtob3N0bmFtZX0ke3BvcnQgPyBgOiR7cG9ydH1gIDogXCJcIn1gO1xuICAgICAgY29uc3Qgc2Vzc2lvbiA9IHRoaXMuZ2V0U2Vzc2lvbihhdXRob3JpdHksIHRoaXMuZGlzYWJsZUNvbmN1cnJlbnRTdHJlYW1zIHx8IGZhbHNlKTtcblxuICAgICAgY29uc3QgcmVqZWN0ID0gKGVycjogRXJyb3IpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuZGlzYWJsZUNvbmN1cnJlbnRTdHJlYW1zKSB7XG4gICAgICAgICAgdGhpcy5kZXN0cm95U2Vzc2lvbihzZXNzaW9uKTtcbiAgICAgICAgfVxuICAgICAgICBmdWxmaWxsZWQgPSB0cnVlO1xuICAgICAgICByZWplY3RPcmlnaW5hbChlcnIpO1xuICAgICAgfTtcblxuICAgICAgY29uc3QgcXVlcnlTdHJpbmcgPSBidWlsZFF1ZXJ5U3RyaW5nKHF1ZXJ5IHx8IHt9KTtcbiAgICAgIC8vIGNyZWF0ZSB0aGUgaHR0cDIgcmVxdWVzdFxuICAgICAgY29uc3QgcmVxID0gc2Vzc2lvbi5yZXF1ZXN0KHtcbiAgICAgICAgLi4ucmVxdWVzdC5oZWFkZXJzLFxuICAgICAgICBbY29uc3RhbnRzLkhUVFAyX0hFQURFUl9QQVRIXTogcXVlcnlTdHJpbmcgPyBgJHtwYXRofT8ke3F1ZXJ5U3RyaW5nfWAgOiBwYXRoLFxuICAgICAgICBbY29uc3RhbnRzLkhUVFAyX0hFQURFUl9NRVRIT0RdOiBtZXRob2QsXG4gICAgICB9KTtcblxuICAgICAgcmVxLm9uKFwicmVzcG9uc2VcIiwgKGhlYWRlcnMpID0+IHtcbiAgICAgICAgY29uc3QgaHR0cFJlc3BvbnNlID0gbmV3IEh0dHBSZXNwb25zZSh7XG4gICAgICAgICAgc3RhdHVzQ29kZTogaGVhZGVyc1tcIjpzdGF0dXNcIl0gfHwgLTEsXG4gICAgICAgICAgaGVhZGVyczogZ2V0VHJhbnNmb3JtZWRIZWFkZXJzKGhlYWRlcnMpLFxuICAgICAgICAgIGJvZHk6IHJlcSxcbiAgICAgICAgfSk7XG4gICAgICAgIGZ1bGZpbGxlZCA9IHRydWU7XG4gICAgICAgIHJlc29sdmUoeyByZXNwb25zZTogaHR0cFJlc3BvbnNlIH0pO1xuICAgICAgICBpZiAodGhpcy5kaXNhYmxlQ29uY3VycmVudFN0cmVhbXMpIHtcbiAgICAgICAgICAvLyBHcmFjZWZ1bGx5IGNsb3NlcyB0aGUgSHR0cDJTZXNzaW9uLCBhbGxvd2luZyBhbnkgZXhpc3Rpbmcgc3RyZWFtcyB0byBjb21wbGV0ZVxuICAgICAgICAgIC8vIG9uIHRoZWlyIG93biBhbmQgcHJldmVudGluZyBuZXcgSHR0cDJTdHJlYW0gaW5zdGFuY2VzIGZyb20gYmVpbmcgY3JlYXRlZC5cbiAgICAgICAgICBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgdGhpcy5kZWxldGVTZXNzaW9uRnJvbUNhY2hlKGF1dGhvcml0eSwgc2Vzc2lvbik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXF1ZXN0VGltZW91dCA9IHRoaXMucmVxdWVzdFRpbWVvdXQ7XG4gICAgICBpZiAocmVxdWVzdFRpbWVvdXQpIHtcbiAgICAgICAgcmVxLnNldFRpbWVvdXQocmVxdWVzdFRpbWVvdXQsICgpID0+IHtcbiAgICAgICAgICByZXEuY2xvc2UoKTtcbiAgICAgICAgICBjb25zdCB0aW1lb3V0RXJyb3IgPSBuZXcgRXJyb3IoYFN0cmVhbSB0aW1lZCBvdXQgYmVjYXVzZSBvZiBubyBhY3Rpdml0eSBmb3IgJHtyZXF1ZXN0VGltZW91dH0gbXNgKTtcbiAgICAgICAgICB0aW1lb3V0RXJyb3IubmFtZSA9IFwiVGltZW91dEVycm9yXCI7XG4gICAgICAgICAgcmVqZWN0KHRpbWVvdXRFcnJvcik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoYWJvcnRTaWduYWwpIHtcbiAgICAgICAgYWJvcnRTaWduYWwub25hYm9ydCA9ICgpID0+IHtcbiAgICAgICAgICByZXEuY2xvc2UoKTtcbiAgICAgICAgICBjb25zdCBhYm9ydEVycm9yID0gbmV3IEVycm9yKFwiUmVxdWVzdCBhYm9ydGVkXCIpO1xuICAgICAgICAgIGFib3J0RXJyb3IubmFtZSA9IFwiQWJvcnRFcnJvclwiO1xuICAgICAgICAgIHJlamVjdChhYm9ydEVycm9yKTtcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgLy8gU2V0IHVwIGhhbmRsZXJzIGZvciBlcnJvcnNcbiAgICAgIHJlcS5vbihcImZyYW1lRXJyb3JcIiwgcmVqZWN0KTtcbiAgICAgIHJlcS5vbihcImVycm9yXCIsIHJlamVjdCk7XG4gICAgICByZXEub24oXCJnb2F3YXlcIiwgcmVqZWN0KTtcbiAgICAgIHJlcS5vbihcImFib3J0ZWRcIiwgcmVqZWN0KTtcblxuICAgICAgLy8gVGhlIEhUVFAvMiBlcnJvciBjb2RlIHVzZWQgd2hlbiBjbG9zaW5nIHRoZSBzdHJlYW0gY2FuIGJlIHJldHJpZXZlZCB1c2luZyB0aGVcbiAgICAgIC8vIGh0dHAyc3RyZWFtLnJzdENvZGUgcHJvcGVydHkuIElmIHRoZSBjb2RlIGlzIGFueSB2YWx1ZSBvdGhlciB0aGFuIE5HSFRUUDJfTk9fRVJST1IgKDApLFxuICAgICAgLy8gYW4gJ2Vycm9yJyBldmVudCB3aWxsIGhhdmUgYWxzbyBiZWVuIGVtaXR0ZWQuXG4gICAgICByZXEub24oXCJjbG9zZVwiLCAoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVDb25jdXJyZW50U3RyZWFtcykge1xuICAgICAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZnVsZmlsbGVkKSB7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIlVuZXhwZWN0ZWQgZXJyb3I6IGh0dHAyIHJlcXVlc3QgZGlkIG5vdCBnZXQgYSByZXNwb25zZVwiKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB3cml0ZVJlcXVlc3RCb2R5KHJlcSwgcmVxdWVzdCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIHNlc3Npb24gZm9yIHRoZSBnaXZlbiBVUkwuXG4gICAqXG4gICAqIEBwYXJhbSBhdXRob3JpdHkgVGhlIFVSTCB0byBjcmVhdGUgYSBzZXNzaW9uIGZvci5cbiAgICogQHBhcmFtIGRpc2FibGVDb25jdXJyZW50U3RyZWFtcyBJZiB0cnVlLCBhIG5ldyBzZXNzaW9uIHdpbGwgYmUgY3JlYXRlZCBmb3IgZWFjaCByZXF1ZXN0LlxuICAgKiBAcmV0dXJucyBBIHNlc3Npb24gZm9yIHRoZSBnaXZlbiBVUkwuXG4gICAqL1xuICBwcml2YXRlIGdldFNlc3Npb24oYXV0aG9yaXR5OiBzdHJpbmcsIGRpc2FibGVDb25jdXJyZW50U3RyZWFtczogYm9vbGVhbik6IENsaWVudEh0dHAyU2Vzc2lvbiB7XG4gICAgY29uc3Qgc2Vzc2lvbkNhY2hlID0gdGhpcy5zZXNzaW9uQ2FjaGU7XG4gICAgY29uc3QgZXhpc3RpbmdTZXNzaW9ucyA9IHNlc3Npb25DYWNoZS5nZXQoYXV0aG9yaXR5KSB8fCBbXTtcblxuICAgIC8vIElmIGNvbmN1cnJlbnQgc3RyZWFtcyBhcmUgbm90IGRpc2FibGVkLCB3ZSBjYW4gdXNlIHRoZSBleGlzdGluZyBzZXNzaW9uLlxuICAgIGlmIChleGlzdGluZ1Nlc3Npb25zLmxlbmd0aCA+IDAgJiYgIWRpc2FibGVDb25jdXJyZW50U3RyZWFtcykgcmV0dXJuIGV4aXN0aW5nU2Vzc2lvbnNbMF07XG5cbiAgICBjb25zdCBuZXdTZXNzaW9uID0gY29ubmVjdChhdXRob3JpdHkpO1xuICAgIGNvbnN0IGRlc3Ryb3lTZXNzaW9uQ2IgPSAoKSA9PiB7XG4gICAgICB0aGlzLmRlc3Ryb3lTZXNzaW9uKG5ld1Nlc3Npb24pO1xuICAgICAgdGhpcy5kZWxldGVTZXNzaW9uRnJvbUNhY2hlKGF1dGhvcml0eSwgbmV3U2Vzc2lvbik7XG4gICAgfTtcbiAgICBuZXdTZXNzaW9uLm9uKFwiZ29hd2F5XCIsIGRlc3Ryb3lTZXNzaW9uQ2IpO1xuICAgIG5ld1Nlc3Npb24ub24oXCJlcnJvclwiLCBkZXN0cm95U2Vzc2lvbkNiKTtcbiAgICBuZXdTZXNzaW9uLm9uKFwiZnJhbWVFcnJvclwiLCBkZXN0cm95U2Vzc2lvbkNiKTtcblxuICAgIGNvbnN0IHNlc3Npb25UaW1lb3V0ID0gdGhpcy5zZXNzaW9uVGltZW91dDtcbiAgICBpZiAoc2Vzc2lvblRpbWVvdXQpIHtcbiAgICAgIG5ld1Nlc3Npb24uc2V0VGltZW91dChzZXNzaW9uVGltZW91dCwgZGVzdHJveVNlc3Npb25DYik7XG4gICAgfVxuXG4gICAgZXhpc3RpbmdTZXNzaW9ucy5wdXNoKG5ld1Nlc3Npb24pO1xuICAgIHNlc3Npb25DYWNoZS5zZXQoYXV0aG9yaXR5LCBleGlzdGluZ1Nlc3Npb25zKTtcblxuICAgIHJldHVybiBuZXdTZXNzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIERlc3Ryb3lzIGEgc2Vzc2lvbi5cbiAgICogQHBhcmFtIHNlc3Npb24gVGhlIHNlc3Npb24gdG8gZGVzdHJveS5cbiAgICovXG4gIHByaXZhdGUgZGVzdHJveVNlc3Npb24oc2Vzc2lvbjogQ2xpZW50SHR0cDJTZXNzaW9uKTogdm9pZCB7XG4gICAgaWYgKCFzZXNzaW9uLmRlc3Ryb3llZCkge1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZSBhIHNlc3Npb24gZnJvbSB0aGUgY29ubmVjdGlvbiBwb29sLlxuICAgKiBAcGFyYW0gYXV0aG9yaXR5IFRoZSBhdXRob3JpdHkgb2YgdGhlIHNlc3Npb24gdG8gZGVsZXRlLlxuICAgKiBAcGFyYW0gc2Vzc2lvbiBUaGUgc2Vzc2lvbiB0byBkZWxldGUuXG4gICAqL1xuICBwcml2YXRlIGRlbGV0ZVNlc3Npb25Gcm9tQ2FjaGUoYXV0aG9yaXR5OiBzdHJpbmcsIHNlc3Npb246IENsaWVudEh0dHAyU2Vzc2lvbik6IHZvaWQge1xuICAgIGNvbnN0IGV4aXN0aW5nU2Vzc2lvbnMgPSB0aGlzLnNlc3Npb25DYWNoZS5nZXQoYXV0aG9yaXR5KSB8fCBbXTtcbiAgICBpZiAoIWV4aXN0aW5nU2Vzc2lvbnMuaW5jbHVkZXMoc2Vzc2lvbikpIHtcbiAgICAgIC8vIElmIHRoZSBzZXNzaW9uIGlzIG5vdCBpbiB0aGUgY2FjaGUsIGl0IGhhcyBhbHJlYWR5IGJlZW4gZGVsZXRlZC5cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5zZXNzaW9uQ2FjaGUuc2V0KFxuICAgICAgYXV0aG9yaXR5LFxuICAgICAgZXhpc3RpbmdTZXNzaW9ucy5maWx0ZXIoKHMpID0+IHMgIT09IHNlc3Npb24pXG4gICAgKTtcbiAgfVxufVxuIl19

@@ -1,2 +0,2 @@

import { __assign, __read, __values } from "tslib";
import { __assign, __values } from "tslib";
import { HttpResponse } from "@aws-sdk/protocol-http";

@@ -9,15 +9,16 @@ import { buildQueryString } from "@aws-sdk/querystring-builder";

function NodeHttp2Handler(_a) {
var _b = _a === void 0 ? {} : _a, requestTimeout = _b.requestTimeout, sessionTimeout = _b.sessionTimeout;
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.connectionPool = new Map();
this.disableConcurrentStreams = disableConcurrentStreams;
this.sessionCache = new Map();
}
NodeHttp2Handler.prototype.destroy = function () {
var e_1, _a;
var _this = this;
try {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (var _b = __values(this.connectionPool), _c = _b.next(); !_c.done; _c = _b.next()) {
var _d = __read(_c.value, 2), _ = _d[0], http2Session = _d[1];
http2Session.destroy();
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); });
}

@@ -32,3 +33,3 @@ }

}
this.connectionPool.clear();
this.sessionCache.clear();
};

@@ -43,17 +44,23 @@ NodeHttp2Handler.prototype.handle = function (request, _a) {

var fulfilled = false;
var reject = function (err) {
fulfilled = true;
rejectOriginal(err);
};
// if the request was already aborted, prevent doing extra work
if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) {
fulfilled = true;
var abortError = new Error("Request aborted");
abortError.name = "AbortError";
reject(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 || {});
// create the http2 request
var req = _this.getSession(protocol + "//" + hostname + (port ? ":" + port : "")).request(__assign(__assign({}, request.headers), (_a = {}, _a[constants.HTTP2_HEADER_PATH] = queryString ? path + "?" + queryString : path, _a[constants.HTTP2_HEADER_METHOD] = method, _a)));
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) {

@@ -67,2 +74,8 @@ var httpResponse = new HttpResponse({

resolve({ response: httpResponse });
if (_this.disableConcurrentStreams) {
// Gracefully closes the Http2Session, allowing any existing streams to complete
// on their own and preventing new Http2Stream instances from being created.
session.close();
_this.deleteSessionFromCache(authority, session);
}
});

@@ -95,2 +108,5 @@ var requestTimeout = _this.requestTimeout;

req.on("close", function () {
if (_this.disableConcurrentStreams) {
session.destroy();
}
if (!fulfilled) {

@@ -103,12 +119,20 @@ reject(new Error("Unexpected error: http2 request did not get a response"));

};
NodeHttp2Handler.prototype.getSession = function (authority) {
/**
* Returns a session for the given URL.
*
* @param authority The URL to create a session for.
* @param disableConcurrentStreams If true, a new session will be created for each request.
* @returns A session for the given URL.
*/
NodeHttp2Handler.prototype.getSession = function (authority, disableConcurrentStreams) {
var _this = this;
var connectionPool = this.connectionPool;
var existingSession = connectionPool.get(authority);
if (existingSession)
return existingSession;
var sessionCache = this.sessionCache;
var existingSessions = sessionCache.get(authority) || [];
// If concurrent streams are not disabled, we can use the existing session.
if (existingSessions.length > 0 && !disableConcurrentStreams)
return existingSessions[0];
var newSession = connect(authority);
connectionPool.set(authority, newSession);
var destroySessionCb = function () {
_this.destroySession(authority, newSession);
_this.destroySession(newSession);
_this.deleteSessionFromCache(authority, newSession);
};

@@ -120,26 +144,13 @@ newSession.on("goaway", destroySessionCb);

if (sessionTimeout) {
newSession.setTimeout(sessionTimeout, function () {
if (connectionPool.get(authority) === newSession) {
newSession.close();
connectionPool.delete(authority);
}
});
newSession.setTimeout(sessionTimeout, destroySessionCb);
}
existingSessions.push(newSession);
sessionCache.set(authority, existingSessions);
return newSession;
};
/**
* Destroy a session immediately and remove it from the http2 pool.
*
* This check ensures that the session is only closed once
* and that an event on one session does not close a different session.
* Destroys a session.
* @param session The session to destroy.
*/
NodeHttp2Handler.prototype.destroySession = function (authority, session) {
if (this.connectionPool.get(authority) !== session) {
// Already closed?
return;
}
this.connectionPool.delete(authority);
session.removeAllListeners("goaway");
session.removeAllListeners("error");
session.removeAllListeners("frameError");
NodeHttp2Handler.prototype.destroySession = function (session) {
if (!session.destroyed) {

@@ -149,5 +160,18 @@ session.destroy();

};
/**
* Delete a session from the connection pool.
* @param authority The authority of the session to delete.
* @param session The session to delete.
*/
NodeHttp2Handler.prototype.deleteSessionFromCache = function (authority, session) {
var existingSessions = this.sessionCache.get(authority) || [];
if (!existingSessions.includes(session)) {
// If the session is not in the cache, it has already been deleted.
return;
}
this.sessionCache.set(authority, existingSessions.filter(function (s) { return s !== session; }));
};
return NodeHttp2Handler;
}());
export { NodeHttp2Handler };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1odHRwMi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL25vZGUtaHR0cDItaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUE0QixZQUFZLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNoRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUVoRSxPQUFPLEVBQXNCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFFL0QsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFvQnhEO0lBTUUsMEJBQVksRUFBZ0U7WUFBaEUscUJBQThELEVBQUUsS0FBQSxFQUE5RCxjQUFjLG9CQUFBLEVBQUUsY0FBYyxvQkFBQTtRQUY1QixhQUFRLEdBQUcsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFHbkQsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLEdBQUcsRUFBOEIsQ0FBQztJQUM5RCxDQUFDO0lBRUQsa0NBQU8sR0FBUDs7O1lBQ0UsNkRBQTZEO1lBQzdELEtBQWdDLElBQUEsS0FBQSxTQUFBLElBQUksQ0FBQyxjQUFjLENBQUEsZ0JBQUEsNEJBQUU7Z0JBQTFDLElBQUEsS0FBQSxtQkFBaUIsRUFBaEIsQ0FBQyxRQUFBLEVBQUUsWUFBWSxRQUFBO2dCQUN6QixZQUFZLENBQUMsT0FBTyxFQUFFLENBQUM7YUFDeEI7Ozs7Ozs7OztRQUNELElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUVELGlDQUFNLEdBQU4sVUFBTyxPQUFvQixFQUFFLEVBQXdDO1FBQXJF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IGZyb20gXCJAYXdzLXNkay9wcm90b2NvbC1odHRwXCI7XG5pbXBvcnQgeyBidWlsZFF1ZXJ5U3RyaW5nIH0gZnJvbSBcIkBhd3Mtc2RrL3F1ZXJ5c3RyaW5nLWJ1aWxkZXJcIjtcbmltcG9ydCB7IEh0dHBIYW5kbGVyT3B0aW9ucyB9IGZyb20gXCJAYXdzLXNkay90eXBlc1wiO1xuaW1wb3J0IHsgQ2xpZW50SHR0cDJTZXNzaW9uLCBjb25uZWN0LCBjb25zdGFudHMgfSBmcm9tIFwiaHR0cDJcIjtcblxuaW1wb3J0IHsgZ2V0VHJhbnNmb3JtZWRIZWFkZXJzIH0gZnJvbSBcIi4vZ2V0LXRyYW5zZm9ybWVkLWhlYWRlcnNcIjtcbmltcG9ydCB7IHdyaXRlUmVxdWVzdEJvZHkgfSBmcm9tIFwiLi93cml0ZS1yZXF1ZXN0LWJvZHlcIjtcblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBodHRwMiBvcHRpb25zIHRoYXQgY2FuIGJlIHBhc3NlZCB0byBhIG5vZGUgaHR0cDIgY2xpZW50LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5vZGVIdHRwMkhhbmRsZXJPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRoYXQgYSBzdHJlYW0gbWF5IHJlbWFpbiBpZGxlIGJlZm9yZSBpdFxuICAgKiBpcyBjbG9zZWQuXG4gICAqL1xuICByZXF1ZXN0VGltZW91dD86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIG1heGltdW0gdGltZSBpbiBtaWxsaXNlY29uZHMgdGhhdCBhIHNlc3Npb24gb3Igc29ja2V0IG1heSByZW1haW4gaWRsZVxuICAgKiBiZWZvcmUgaXQgaXMgY2xvc2VkLlxuICAgKiBodHRwczovL25vZGVqcy5vcmcvZG9jcy9sYXRlc3QtdjEyLngvYXBpL2h0dHAyLmh0bWwjaHR0cDJfaHR0cDJzZXNzaW9uX2FuZF9zb2NrZXRzXG4gICAqL1xuICBzZXNzaW9uVGltZW91dD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIE5vZGVIdHRwMkhhbmRsZXIgaW1wbGVtZW50cyBIdHRwSGFuZGxlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVxdWVzdFRpbWVvdXQ/OiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2Vzc2lvblRpbWVvdXQ/OiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29ubmVjdGlvblBvb2w6IE1hcDxzdHJpbmcsIENsaWVudEh0dHAyU2Vzc2lvbj47XG4gIHB1YmxpYyByZWFkb25seSBtZXRhZGF0YSA9IHsgaGFuZGxlclByb3RvY29sOiBcImgyXCIgfTtcblxuICBjb25zdHJ1Y3Rvcih7IHJlcXVlc3RUaW1lb3V0LCBzZXNzaW9uVGltZW91dCB9OiBOb2RlSHR0cDJIYW5kbGVyT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5yZXF1ZXN0VGltZW91dCA9IHJlcXVlc3RUaW1lb3V0O1xuICAgIHRoaXMuc2Vzc2lvblRpbWVvdXQgPSBzZXNzaW9uVGltZW91dDtcbiAgICB0aGlzLmNvbm5lY3Rpb25Qb29sID0gbmV3IE1hcDxzdHJpbmcsIENsaWVudEh0dHAyU2Vzc2lvbj4oKTtcbiAgfVxuXG4gIGRlc3Ryb3koKTogdm9pZCB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIGZvciAoY29uc3QgW18sIGh0dHAyU2Vzc2lvbl0gb2YgdGhpcy5jb25uZWN0aW9uUG9vbCkge1xuICAgICAgaHR0cDJTZXNzaW9uLmRlc3Ryb3koKTtcbiAgICB9XG4gICAgdGhpcy5jb25uZWN0aW9uUG9vbC5jbGVhcigpO1xuICB9XG5cbiAgaGFuZGxlKHJlcXVlc3Q6IEh0dHBSZXF1ZXN0LCB7IGFib3J0U2lnbmFsIH06IEh0dHBIYW5kbGVyT3B0aW9ucyA9IHt9KTogUHJvbWlzZTx7IHJlc3BvbnNlOiBIdHRwUmVzcG9uc2UgfT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0T3JpZ2luYWwpID0+IHtcbiAgICAgIC8vIEl0J3MgcmVkdW5kYW50IHRvIHRyYWNrIGZ1bGZpbGxlZCBiZWNhdXNlIHByb21pc2VzIHVzZSB0aGUgZmlyc3QgcmVzb2x1dGlvbi9yZWplY3Rpb25cbiAgICAgIC8vIGJ1dCBhdm9pZHMgZ2VuZXJhdGluZyB1bm5lY2Vzc2FyeSBzdGFjayB0cmFjZXMgaW4gdGhlIFwiY2xvc2VcIiBldmVudCBoYW5kbGVyLlxuICAgICAgbGV0IGZ1bGZpbGxlZCA9IGZhbHNlO1xuICAgICAgY29uc3QgcmVqZWN0ID0gKGVycjogRXJyb3IpID0+IHtcbiAgICAgICAgZnVsZmlsbGVkID0gdHJ1ZTtcbiAgICAgICAgcmVqZWN0T3JpZ2luYWwoZXJyKTtcbiAgICAgIH07XG4gICAgICAvLyBpZiB0aGUgcmVxdWVzdCB3YXMgYWxyZWFkeSBhYm9ydGVkLCBwcmV2ZW50IGRvaW5nIGV4dHJhIHdvcmtcbiAgICAgIGlmIChhYm9ydFNpZ25hbD8uYWJvcnRlZCkge1xuICAgICAgICBjb25zdCBhYm9ydEVycm9yID0gbmV3IEVycm9yKFwiUmVxdWVzdCBhYm9ydGVkXCIpO1xuICAgICAgICBhYm9ydEVycm9yLm5hbWUgPSBcIkFib3J0RXJyb3JcIjtcbiAgICAgICAgcmVqZWN0KGFib3J0RXJyb3IpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgaG9zdG5hbWUsIG1ldGhvZCwgcG9ydCwgcHJvdG9jb2wsIHBhdGgsIHF1ZXJ5IH0gPSByZXF1ZXN0O1xuICAgICAgY29uc3QgcXVlcnlTdHJpbmcgPSBidWlsZFF1ZXJ5U3RyaW5nKHF1ZXJ5IHx8IHt9KTtcblxuICAgICAgLy8gY3JlYXRlIHRoZSBodHRwMiByZXF1ZXN0XG4gICAgICBjb25zdCByZXEgPSB0aGlzLmdldFNlc3Npb24oYCR7cHJvdG9jb2x9Ly8ke2hvc3RuYW1lfSR7cG9ydCA/IGA6JHtwb3J0fWAgOiBcIlwifWApLnJlcXVlc3Qoe1xuICAgICAgICAuLi5yZXF1ZXN0LmhlYWRlcnMsXG4gICAgICAgIFtjb25zdGFudHMuSFRUUDJfSEVBREVSX1BBVEhdOiBxdWVyeVN0cmluZyA/IGAke3BhdGh9PyR7cXVlcnlTdHJpbmd9YCA6IHBhdGgsXG4gICAgICAgIFtjb25zdGFudHMuSFRUUDJfSEVBREVSX01FVEhPRF06IG1ldGhvZCxcbiAgICAgIH0pO1xuXG4gICAgICByZXEub24oXCJyZXNwb25zZVwiLCAoaGVhZGVycykgPT4ge1xuICAgICAgICBjb25zdCBodHRwUmVzcG9uc2UgPSBuZXcgSHR0cFJlc3BvbnNlKHtcbiAgICAgICAgICBzdGF0dXNDb2RlOiBoZWFkZXJzW1wiOnN0YXR1c1wiXSB8fCAtMSxcbiAgICAgICAgICBoZWFkZXJzOiBnZXRUcmFuc2Zvcm1lZEhlYWRlcnMoaGVhZGVycyksXG4gICAgICAgICAgYm9keTogcmVxLFxuICAgICAgICB9KTtcbiAgICAgICAgZnVsZmlsbGVkID0gdHJ1ZTtcbiAgICAgICAgcmVzb2x2ZSh7IHJlc3BvbnNlOiBodHRwUmVzcG9uc2UgfSk7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVxdWVzdFRpbWVvdXQgPSB0aGlzLnJlcXVlc3RUaW1lb3V0O1xuICAgICAgaWYgKHJlcXVlc3RUaW1lb3V0KSB7XG4gICAgICAgIHJlcS5zZXRUaW1lb3V0KHJlcXVlc3RUaW1lb3V0LCAoKSA9PiB7XG4gICAgICAgICAgcmVxLmNsb3NlKCk7XG4gICAgICAgICAgY29uc3QgdGltZW91dEVycm9yID0gbmV3IEVycm9yKGBTdHJlYW0gdGltZWQgb3V0IGJlY2F1c2Ugb2Ygbm8gYWN0aXZpdHkgZm9yICR7cmVxdWVzdFRpbWVvdXR9IG1zYCk7XG4gICAgICAgICAgdGltZW91dEVycm9yLm5hbWUgPSBcIlRpbWVvdXRFcnJvclwiO1xuICAgICAgICAgIHJlamVjdCh0aW1lb3V0RXJyb3IpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFib3J0U2lnbmFsKSB7XG4gICAgICAgIGFib3J0U2lnbmFsLm9uYWJvcnQgPSAoKSA9PiB7XG4gICAgICAgICAgcmVxLmNsb3NlKCk7XG4gICAgICAgICAgY29uc3QgYWJvcnRFcnJvciA9IG5ldyBFcnJvcihcIlJlcXVlc3QgYWJvcnRlZFwiKTtcbiAgICAgICAgICBhYm9ydEVycm9yLm5hbWUgPSBcIkFib3J0RXJyb3JcIjtcbiAgICAgICAgICByZWplY3QoYWJvcnRFcnJvcik7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFNldCB1cCBoYW5kbGVycyBmb3IgZXJyb3JzXG4gICAgICByZXEub24oXCJmcmFtZUVycm9yXCIsIHJlamVjdCk7XG4gICAgICByZXEub24oXCJlcnJvclwiLCByZWplY3QpO1xuICAgICAgcmVxLm9uKFwiZ29hd2F5XCIsIHJlamVjdCk7XG4gICAgICByZXEub24oXCJhYm9ydGVkXCIsIHJlamVjdCk7XG5cbiAgICAgIC8vIFRoZSBIVFRQLzIgZXJyb3IgY29kZSB1c2VkIHdoZW4gY2xvc2luZyB0aGUgc3RyZWFtIGNhbiBiZSByZXRyaWV2ZWQgdXNpbmcgdGhlXG4gICAgICAvLyBodHRwMnN0cmVhbS5yc3RDb2RlIHByb3BlcnR5LiBJZiB0aGUgY29kZSBpcyBhbnkgdmFsdWUgb3RoZXIgdGhhbiBOR0hUVFAyX05PX0VSUk9SICgwKSxcbiAgICAgIC8vIGFuICdlcnJvcicgZXZlbnQgd2lsbCBoYXZlIGFsc28gYmVlbiBlbWl0dGVkLlxuICAgICAgcmVxLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgICBpZiAoIWZ1bGZpbGxlZCkge1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJVbmV4cGVjdGVkIGVycm9yOiBodHRwMiByZXF1ZXN0IGRpZCBub3QgZ2V0IGEgcmVzcG9uc2VcIikpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHdyaXRlUmVxdWVzdEJvZHkocmVxLCByZXF1ZXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0U2Vzc2lvbihhdXRob3JpdHk6IHN0cmluZyk6IENsaWVudEh0dHAyU2Vzc2lvbiB7XG4gICAgY29uc3QgY29ubmVjdGlvblBvb2wgPSB0aGlzLmNvbm5lY3Rpb25Qb29sO1xuICAgIGNvbnN0IGV4aXN0aW5nU2Vzc2lvbiA9IGNvbm5lY3Rpb25Qb29sLmdldChhdXRob3JpdHkpO1xuICAgIGlmIChleGlzdGluZ1Nlc3Npb24pIHJldHVybiBleGlzdGluZ1Nlc3Npb247XG5cbiAgICBjb25zdCBuZXdTZXNzaW9uID0gY29ubmVjdChhdXRob3JpdHkpO1xuICAgIGNvbm5lY3Rpb25Qb29sLnNldChhdXRob3JpdHksIG5ld1Nlc3Npb24pO1xuICAgIGNvbnN0IGRlc3Ryb3lTZXNzaW9uQ2IgPSAoKSA9PiB7XG4gICAgICB0aGlzLmRlc3Ryb3lTZXNzaW9uKGF1dGhvcml0eSwgbmV3U2Vzc2lvbik7XG4gICAgfTtcbiAgICBuZXdTZXNzaW9uLm9uKFwiZ29hd2F5XCIsIGRlc3Ryb3lTZXNzaW9uQ2IpO1xuICAgIG5ld1Nlc3Npb24ub24oXCJlcnJvclwiLCBkZXN0cm95U2Vzc2lvbkNiKTtcbiAgICBuZXdTZXNzaW9uLm9uKFwiZnJhbWVFcnJvclwiLCBkZXN0cm95U2Vzc2lvbkNiKTtcblxuICAgIGNvbnN0IHNlc3Npb25UaW1lb3V0ID0gdGhpcy5zZXNzaW9uVGltZW91dDtcbiAgICBpZiAoc2Vzc2lvblRpbWVvdXQpIHtcbiAgICAgIG5ld1Nlc3Npb24uc2V0VGltZW91dChzZXNzaW9uVGltZW91dCwgKCkgPT4ge1xuICAgICAgICBpZiAoY29ubmVjdGlvblBvb2wuZ2V0KGF1dGhvcml0eSkgPT09IG5ld1Nlc3Npb24pIHtcbiAgICAgICAgICBuZXdTZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgICAgY29ubmVjdGlvblBvb2wuZGVsZXRlKGF1dGhvcml0eSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gbmV3U2Vzc2lvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXN0cm95IGEgc2Vzc2lvbiBpbW1lZGlhdGVseSBhbmQgcmVtb3ZlIGl0IGZyb20gdGhlIGh0dHAyIHBvb2wuXG4gICAqXG4gICAqIFRoaXMgY2hlY2sgZW5zdXJlcyB0aGF0IHRoZSBzZXNzaW9uIGlzIG9ubHkgY2xvc2VkIG9uY2VcbiAgICogYW5kIHRoYXQgYW4gZXZlbnQgb24gb25lIHNlc3Npb24gZG9lcyBub3QgY2xvc2UgYSBkaWZmZXJlbnQgc2Vzc2lvbi5cbiAgICovXG4gIHByaXZhdGUgZGVzdHJveVNlc3Npb24oYXV0aG9yaXR5OiBzdHJpbmcsIHNlc3Npb246IENsaWVudEh0dHAyU2Vzc2lvbik6IHZvaWQge1xuICAgIGlmICh0aGlzLmNvbm5lY3Rpb25Qb29sLmdldChhdXRob3JpdHkpICE9PSBzZXNzaW9uKSB7XG4gICAgICAvLyBBbHJlYWR5IGNsb3NlZD9cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jb25uZWN0aW9uUG9vbC5kZWxldGUoYXV0aG9yaXR5KTtcbiAgICBzZXNzaW9uLnJlbW92ZUFsbExpc3RlbmVycyhcImdvYXdheVwiKTtcbiAgICBzZXNzaW9uLnJlbW92ZUFsbExpc3RlbmVycyhcImVycm9yXCIpO1xuICAgIHNlc3Npb24ucmVtb3ZlQWxsTGlzdGVuZXJzKFwiZnJhbWVFcnJvclwiKTtcbiAgICBpZiAoIXNlc3Npb24uZGVzdHJveWVkKSB7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1odHRwMi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL25vZGUtaHR0cDItaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUE0QixZQUFZLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNoRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUVoRSxPQUFPLEVBQXNCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFFL0QsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUE0QnhEO0lBUUUsMEJBQVksRUFBMEY7WUFBMUYscUJBQXdGLEVBQUUsS0FBQSxFQUF4RixjQUFjLG9CQUFBLEVBQUUsY0FBYyxvQkFBQSxFQUFFLHdCQUF3Qiw4QkFBQTtRQUh0RCxhQUFRLEdBQUcsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFJbkQsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLHdCQUF3QixHQUFHLHdCQUF3QixDQUFDO1FBQ3pELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQWdDLENBQUM7SUFDOUQsQ0FBQztJQUVELGtDQUFPLEdBQVA7O1FBQUEsaUJBS0M7O1lBSkMsS0FBdUIsSUFBQSxLQUFBLFNBQUEsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQSxnQkFBQSw0QkFBRTtnQkFBOUMsSUFBTSxRQUFRLFdBQUE7Z0JBQ2pCLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBQyxPQUFPLElBQUssT0FBQSxLQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxFQUE1QixDQUE0QixDQUFDLENBQUM7YUFD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QVksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFFOUMsT0FBTyxVQUFVLENBQUM7SUFDcEIsQ0FBQztJQUVEOzs7T0FHRztJQUNLLHlDQUFjLEdBQXRCLFVBQXVCLE9BQTJCO1FBQ2hELElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFO1lBQ3RCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNuQjtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssaURBQXNCLEdBQTlCLFVBQStCLFNBQWlCLEVBQUUsT0FBMkI7UUFDM0UsSUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUN2QyxtRUFBbUU7WUFDbkUsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQ25CLFNBQVMsRUFDVCxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsVUFBQyxDQUFDLElBQUssT0FBQSxDQUFDLEtBQUssT0FBTyxFQUFiLENBQWEsQ0FBQyxDQUM5QyxDQUFDO0lBQ0osQ0FBQztJQUNILHVCQUFDO0FBQUQsQ0FBQyxBQTlLRCxJQThLQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBIYW5kbGVyLCBIdHRwUmVxdWVzdCwgSHR0cFJlc3BvbnNlIH0gZnJvbSBcIkBhd3Mtc2RrL3Byb3RvY29sLWh0dHBcIjtcbmltcG9ydCB7IGJ1aWxkUXVlcnlTdHJpbmcgfSBmcm9tIFwiQGF3cy1zZGsvcXVlcnlzdHJpbmctYnVpbGRlclwiO1xuaW1wb3J0IHsgSHR0cEhhbmRsZXJPcHRpb25zIH0gZnJvbSBcIkBhd3Mtc2RrL3R5cGVzXCI7XG5pbXBvcnQgeyBDbGllbnRIdHRwMlNlc3Npb24sIGNvbm5lY3QsIGNvbnN0YW50cyB9IGZyb20gXCJodHRwMlwiO1xuXG5pbXBvcnQgeyBnZXRUcmFuc2Zvcm1lZEhlYWRlcnMgfSBmcm9tIFwiLi9nZXQtdHJhbnNmb3JtZWQtaGVhZGVyc1wiO1xuaW1wb3J0IHsgd3JpdGVSZXF1ZXN0Qm9keSB9IGZyb20gXCIuL3dyaXRlLXJlcXVlc3QtYm9keVwiO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIGh0dHAyIG9wdGlvbnMgdGhhdCBjYW4gYmUgcGFzc2VkIHRvIGEgbm9kZSBodHRwMiBjbGllbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZUh0dHAySGFuZGxlck9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIG1heGltdW0gdGltZSBpbiBtaWxsaXNlY29uZHMgdGhhdCBhIHN0cmVhbSBtYXkgcmVtYWluIGlkbGUgYmVmb3JlIGl0XG4gICAqIGlzIGNsb3NlZC5cbiAgICovXG4gIHJlcXVlc3RUaW1lb3V0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSB0aW1lIGluIG1pbGxpc2Vjb25kcyB0aGF0IGEgc2Vzc2lvbiBvciBzb2NrZXQgbWF5IHJlbWFpbiBpZGxlXG4gICAqIGJlZm9yZSBpdCBpcyBjbG9zZWQuXG4gICAqIGh0dHBzOi8vbm9kZWpzLm9yZy9kb2NzL2xhdGVzdC12MTIueC9hcGkvaHR0cDIuaHRtbCNodHRwMl9odHRwMnNlc3Npb25fYW5kX3NvY2tldHNcbiAgICovXG4gIHNlc3Npb25UaW1lb3V0PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBEaXNhYmxlcyBwcm9jZXNzaW5nIGNvbmN1cnJlbnQgc3RyZWFtcyBvbiBhIENsaWVudEh0dHAyU2Vzc2lvbiBpbnN0YW5jZS4gV2hlbiBzZXRcbiAgICogdG8gdHJ1ZSwgdGhlIGhhbmRsZXIgd2lsbCBjcmVhdGUgYSBuZXcgc2Vzc2lvbiBpbnN0YW5jZSBmb3IgZWFjaCByZXF1ZXN0IHRvIGEgVVJMLlxuICAgKiAqKkRlZmF1bHQ6KiogZmFsc2UuXG4gICAqIGh0dHBzOi8vbm9kZWpzLm9yZy9hcGkvaHR0cDIuaHRtbCNodHRwMl9jbGFzc19jbGllbnRodHRwMnNlc3Npb25cbiAgICovXG4gIGRpc2FibGVDb25jdXJyZW50U3RyZWFtcz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjbGFzcyBOb2RlSHR0cDJIYW5kbGVyIGltcGxlbWVudHMgSHR0cEhhbmRsZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IHJlcXVlc3RUaW1lb3V0PzogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IHNlc3Npb25UaW1lb3V0PzogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGRpc2FibGVDb25jdXJyZW50U3RyZWFtcz86IGJvb2xlYW47XG5cbiAgcHVibGljIHJlYWRvbmx5IG1ldGFkYXRhID0geyBoYW5kbGVyUHJvdG9jb2w6IFwiaDJcIiB9O1xuICBwcml2YXRlIHNlc3Npb25DYWNoZTogTWFwPHN0cmluZywgQ2xpZW50SHR0cDJTZXNzaW9uW10+O1xuXG4gIGNvbnN0cnVjdG9yKHsgcmVxdWVzdFRpbWVvdXQsIHNlc3Npb25UaW1lb3V0LCBkaXNhYmxlQ29uY3VycmVudFN0cmVhbXMgfTogTm9kZUh0dHAySGFuZGxlck9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMucmVxdWVzdFRpbWVvdXQgPSByZXF1ZXN0VGltZW91dDtcbiAgICB0aGlzLnNlc3Npb25UaW1lb3V0ID0gc2Vzc2lvblRpbWVvdXQ7XG4gICAgdGhpcy5kaXNhYmxlQ29uY3VycmVudFN0cmVhbXMgPSBkaXNhYmxlQ29uY3VycmVudFN0cmVhbXM7XG4gICAgdGhpcy5zZXNzaW9uQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgQ2xpZW50SHR0cDJTZXNzaW9uW10+KCk7XG4gIH1cblxuICBkZXN0cm95KCk6IHZvaWQge1xuICAgIGZvciAoY29uc3Qgc2Vzc2lvbnMgb2YgdGhpcy5zZXNzaW9uQ2FjaGUudmFsdWVzKCkpIHtcbiAgICAgIHNlc3Npb25zLmZvckVhY2goKHNlc3Npb24pID0+IHRoaXMuZGVzdHJveVNlc3Npb24oc2Vzc2lvbikpO1xuICAgIH1cbiAgICB0aGlzLnNlc3Npb25DYWNoZS5jbGVhcigpO1xuICB9XG5cbiAgaGFuZGxlKHJlcXVlc3Q6IEh0dHBSZXF1ZXN0LCB7IGFib3J0U2lnbmFsIH06IEh0dHBIYW5kbGVyT3B0aW9ucyA9IHt9KTogUHJvbWlzZTx7IHJlc3BvbnNlOiBIdHRwUmVzcG9uc2UgfT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0T3JpZ2luYWwpID0+IHtcbiAgICAgIC8vIEl0J3MgcmVkdW5kYW50IHRvIHRyYWNrIGZ1bGZpbGxlZCBiZWNhdXNlIHByb21pc2VzIHVzZSB0aGUgZmlyc3QgcmVzb2x1dGlvbi9yZWplY3Rpb25cbiAgICAgIC8vIGJ1dCBhdm9pZHMgZ2VuZXJhdGluZyB1bm5lY2Vzc2FyeSBzdGFjayB0cmFjZXMgaW4gdGhlIFwiY2xvc2VcIiBldmVudCBoYW5kbGVyLlxuICAgICAgbGV0IGZ1bGZpbGxlZCA9IGZhbHNlO1xuXG4gICAgICAvLyBpZiB0aGUgcmVxdWVzdCB3YXMgYWxyZWFkeSBhYm9ydGVkLCBwcmV2ZW50IGRvaW5nIGV4dHJhIHdvcmtcbiAgICAgIGlmIChhYm9ydFNpZ25hbD8uYWJvcnRlZCkge1xuICAgICAgICBmdWxmaWxsZWQgPSB0cnVlO1xuICAgICAgICBjb25zdCBhYm9ydEVycm9yID0gbmV3IEVycm9yKFwiUmVxdWVzdCBhYm9ydGVkXCIpO1xuICAgICAgICBhYm9ydEVycm9yLm5hbWUgPSBcIkFib3J0RXJyb3JcIjtcbiAgICAgICAgcmVqZWN0T3JpZ2luYWwoYWJvcnRFcnJvcik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBob3N0bmFtZSwgbWV0aG9kLCBwb3J0LCBwcm90b2NvbCwgcGF0aCwgcXVlcnkgfSA9IHJlcXVlc3Q7XG4gICAgICBjb25zdCBhdXRob3JpdHkgPSBgJHtwcm90b2NvbH0vLyR7aG9zdG5hbWV9JHtwb3J0ID8gYDoke3BvcnR9YCA6IFwiXCJ9YDtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSB0aGlzLmdldFNlc3Npb24oYXV0aG9yaXR5LCB0aGlzLmRpc2FibGVDb25jdXJyZW50U3RyZWFtcyB8fCBmYWxzZSk7XG5cbiAgICAgIGNvbnN0IHJlamVjdCA9IChlcnI6IEVycm9yKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVDb25jdXJyZW50U3RyZWFtcykge1xuICAgICAgICAgIHRoaXMuZGVzdHJveVNlc3Npb24oc2Vzc2lvbik7XG4gICAgICAgIH1cbiAgICAgICAgZnVsZmlsbGVkID0gdHJ1ZTtcbiAgICAgICAgcmVqZWN0T3JpZ2luYWwoZXJyKTtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHF1ZXJ5U3RyaW5nID0gYnVpbGRRdWVyeVN0cmluZyhxdWVyeSB8fCB7fSk7XG4gICAgICAvLyBjcmVhdGUgdGhlIGh0dHAyIHJlcXVlc3RcbiAgICAgIGNvbnN0IHJlcSA9IHNlc3Npb24ucmVxdWVzdCh7XG4gICAgICAgIC4uLnJlcXVlc3QuaGVhZGVycyxcbiAgICAgICAgW2NvbnN0YW50cy5IVFRQMl9IRUFERVJfUEFUSF06IHF1ZXJ5U3RyaW5nID8gYCR7cGF0aH0/JHtxdWVyeVN0cmluZ31gIDogcGF0aCxcbiAgICAgICAgW2NvbnN0YW50cy5IVFRQMl9IRUFERVJfTUVUSE9EXTogbWV0aG9kLFxuICAgICAgfSk7XG5cbiAgICAgIHJlcS5vbihcInJlc3BvbnNlXCIsIChoZWFkZXJzKSA9PiB7XG4gICAgICAgIGNvbnN0IGh0dHBSZXNwb25zZSA9IG5ldyBIdHRwUmVzcG9uc2Uoe1xuICAgICAgICAgIHN0YXR1c0NvZGU6IGhlYWRlcnNbXCI6c3RhdHVzXCJdIHx8IC0xLFxuICAgICAgICAgIGhlYWRlcnM6IGdldFRyYW5zZm9ybWVkSGVhZGVycyhoZWFkZXJzKSxcbiAgICAgICAgICBib2R5OiByZXEsXG4gICAgICAgIH0pO1xuICAgICAgICBmdWxmaWxsZWQgPSB0cnVlO1xuICAgICAgICByZXNvbHZlKHsgcmVzcG9uc2U6IGh0dHBSZXNwb25zZSB9KTtcbiAgICAgICAgaWYgKHRoaXMuZGlzYWJsZUNvbmN1cnJlbnRTdHJlYW1zKSB7XG4gICAgICAgICAgLy8gR3JhY2VmdWxseSBjbG9zZXMgdGhlIEh0dHAyU2Vzc2lvbiwgYWxsb3dpbmcgYW55IGV4aXN0aW5nIHN0cmVhbXMgdG8gY29tcGxldGVcbiAgICAgICAgICAvLyBvbiB0aGVpciBvd24gYW5kIHByZXZlbnRpbmcgbmV3IEh0dHAyU3RyZWFtIGluc3RhbmNlcyBmcm9tIGJlaW5nIGNyZWF0ZWQuXG4gICAgICAgICAgc2Vzc2lvbi5jbG9zZSgpO1xuICAgICAgICAgIHRoaXMuZGVsZXRlU2Vzc2lvbkZyb21DYWNoZShhdXRob3JpdHksIHNlc3Npb24pO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVxdWVzdFRpbWVvdXQgPSB0aGlzLnJlcXVlc3RUaW1lb3V0O1xuICAgICAgaWYgKHJlcXVlc3RUaW1lb3V0KSB7XG4gICAgICAgIHJlcS5zZXRUaW1lb3V0KHJlcXVlc3RUaW1lb3V0LCAoKSA9PiB7XG4gICAgICAgICAgcmVxLmNsb3NlKCk7XG4gICAgICAgICAgY29uc3QgdGltZW91dEVycm9yID0gbmV3IEVycm9yKGBTdHJlYW0gdGltZWQgb3V0IGJlY2F1c2Ugb2Ygbm8gYWN0aXZpdHkgZm9yICR7cmVxdWVzdFRpbWVvdXR9IG1zYCk7XG4gICAgICAgICAgdGltZW91dEVycm9yLm5hbWUgPSBcIlRpbWVvdXRFcnJvclwiO1xuICAgICAgICAgIHJlamVjdCh0aW1lb3V0RXJyb3IpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFib3J0U2lnbmFsKSB7XG4gICAgICAgIGFib3J0U2lnbmFsLm9uYWJvcnQgPSAoKSA9PiB7XG4gICAgICAgICAgcmVxLmNsb3NlKCk7XG4gICAgICAgICAgY29uc3QgYWJvcnRFcnJvciA9IG5ldyBFcnJvcihcIlJlcXVlc3QgYWJvcnRlZFwiKTtcbiAgICAgICAgICBhYm9ydEVycm9yLm5hbWUgPSBcIkFib3J0RXJyb3JcIjtcbiAgICAgICAgICByZWplY3QoYWJvcnRFcnJvcik7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFNldCB1cCBoYW5kbGVycyBmb3IgZXJyb3JzXG4gICAgICByZXEub24oXCJmcmFtZUVycm9yXCIsIHJlamVjdCk7XG4gICAgICByZXEub24oXCJlcnJvclwiLCByZWplY3QpO1xuICAgICAgcmVxLm9uKFwiZ29hd2F5XCIsIHJlamVjdCk7XG4gICAgICByZXEub24oXCJhYm9ydGVkXCIsIHJlamVjdCk7XG5cbiAgICAgIC8vIFRoZSBIVFRQLzIgZXJyb3IgY29kZSB1c2VkIHdoZW4gY2xvc2luZyB0aGUgc3RyZWFtIGNhbiBiZSByZXRyaWV2ZWQgdXNpbmcgdGhlXG4gICAgICAvLyBodHRwMnN0cmVhbS5yc3RDb2RlIHByb3BlcnR5LiBJZiB0aGUgY29kZSBpcyBhbnkgdmFsdWUgb3RoZXIgdGhhbiBOR0hUVFAyX05PX0VSUk9SICgwKSxcbiAgICAgIC8vIGFuICdlcnJvcicgZXZlbnQgd2lsbCBoYXZlIGFsc28gYmVlbiBlbWl0dGVkLlxuICAgICAgcmVxLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5kaXNhYmxlQ29uY3VycmVudFN0cmVhbXMpIHtcbiAgICAgICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZ1bGZpbGxlZCkge1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJVbmV4cGVjdGVkIGVycm9yOiBodHRwMiByZXF1ZXN0IGRpZCBub3QgZ2V0IGEgcmVzcG9uc2VcIikpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgd3JpdGVSZXF1ZXN0Qm9keShyZXEsIHJlcXVlc3QpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzZXNzaW9uIGZvciB0aGUgZ2l2ZW4gVVJMLlxuICAgKlxuICAgKiBAcGFyYW0gYXV0aG9yaXR5IFRoZSBVUkwgdG8gY3JlYXRlIGEgc2Vzc2lvbiBmb3IuXG4gICAqIEBwYXJhbSBkaXNhYmxlQ29uY3VycmVudFN0cmVhbXMgSWYgdHJ1ZSwgYSBuZXcgc2Vzc2lvbiB3aWxsIGJlIGNyZWF0ZWQgZm9yIGVhY2ggcmVxdWVzdC5cbiAgICogQHJldHVybnMgQSBzZXNzaW9uIGZvciB0aGUgZ2l2ZW4gVVJMLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRTZXNzaW9uKGF1dGhvcml0eTogc3RyaW5nLCBkaXNhYmxlQ29uY3VycmVudFN0cmVhbXM6IGJvb2xlYW4pOiBDbGllbnRIdHRwMlNlc3Npb24ge1xuICAgIGNvbnN0IHNlc3Npb25DYWNoZSA9IHRoaXMuc2Vzc2lvbkNhY2hlO1xuICAgIGNvbnN0IGV4aXN0aW5nU2Vzc2lvbnMgPSBzZXNzaW9uQ2FjaGUuZ2V0KGF1dGhvcml0eSkgfHwgW107XG5cbiAgICAvLyBJZiBjb25jdXJyZW50IHN0cmVhbXMgYXJlIG5vdCBkaXNhYmxlZCwgd2UgY2FuIHVzZSB0aGUgZXhpc3Rpbmcgc2Vzc2lvbi5cbiAgICBpZiAoZXhpc3RpbmdTZXNzaW9ucy5sZW5ndGggPiAwICYmICFkaXNhYmxlQ29uY3VycmVudFN0cmVhbXMpIHJldHVybiBleGlzdGluZ1Nlc3Npb25zWzBdO1xuXG4gICAgY29uc3QgbmV3U2Vzc2lvbiA9IGNvbm5lY3QoYXV0aG9yaXR5KTtcbiAgICBjb25zdCBkZXN0cm95U2Vzc2lvbkNiID0gKCkgPT4ge1xuICAgICAgdGhpcy5kZXN0cm95U2Vzc2lvbihuZXdTZXNzaW9uKTtcbiAgICAgIHRoaXMuZGVsZXRlU2Vzc2lvbkZyb21DYWNoZShhdXRob3JpdHksIG5ld1Nlc3Npb24pO1xuICAgIH07XG4gICAgbmV3U2Vzc2lvbi5vbihcImdvYXdheVwiLCBkZXN0cm95U2Vzc2lvbkNiKTtcbiAgICBuZXdTZXNzaW9uLm9uKFwiZXJyb3JcIiwgZGVzdHJveVNlc3Npb25DYik7XG4gICAgbmV3U2Vzc2lvbi5vbihcImZyYW1lRXJyb3JcIiwgZGVzdHJveVNlc3Npb25DYik7XG5cbiAgICBjb25zdCBzZXNzaW9uVGltZW91dCA9IHRoaXMuc2Vzc2lvblRpbWVvdXQ7XG4gICAgaWYgKHNlc3Npb25UaW1lb3V0KSB7XG4gICAgICBuZXdTZXNzaW9uLnNldFRpbWVvdXQoc2Vzc2lvblRpbWVvdXQsIGRlc3Ryb3lTZXNzaW9uQ2IpO1xuICAgIH1cblxuICAgIGV4aXN0aW5nU2Vzc2lvbnMucHVzaChuZXdTZXNzaW9uKTtcbiAgICBzZXNzaW9uQ2FjaGUuc2V0KGF1dGhvcml0eSwgZXhpc3RpbmdTZXNzaW9ucyk7XG5cbiAgICByZXR1cm4gbmV3U2Vzc2lvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXN0cm95cyBhIHNlc3Npb24uXG4gICAqIEBwYXJhbSBzZXNzaW9uIFRoZSBzZXNzaW9uIHRvIGRlc3Ryb3kuXG4gICAqL1xuICBwcml2YXRlIGRlc3Ryb3lTZXNzaW9uKHNlc3Npb246IENsaWVudEh0dHAyU2Vzc2lvbik6IHZvaWQge1xuICAgIGlmICghc2Vzc2lvbi5kZXN0cm95ZWQpIHtcbiAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgYSBzZXNzaW9uIGZyb20gdGhlIGNvbm5lY3Rpb24gcG9vbC5cbiAgICogQHBhcmFtIGF1dGhvcml0eSBUaGUgYXV0aG9yaXR5IG9mIHRoZSBzZXNzaW9uIHRvIGRlbGV0ZS5cbiAgICogQHBhcmFtIHNlc3Npb24gVGhlIHNlc3Npb24gdG8gZGVsZXRlLlxuICAgKi9cbiAgcHJpdmF0ZSBkZWxldGVTZXNzaW9uRnJvbUNhY2hlKGF1dGhvcml0eTogc3RyaW5nLCBzZXNzaW9uOiBDbGllbnRIdHRwMlNlc3Npb24pOiB2b2lkIHtcbiAgICBjb25zdCBleGlzdGluZ1Nlc3Npb25zID0gdGhpcy5zZXNzaW9uQ2FjaGUuZ2V0KGF1dGhvcml0eSkgfHwgW107XG4gICAgaWYgKCFleGlzdGluZ1Nlc3Npb25zLmluY2x1ZGVzKHNlc3Npb24pKSB7XG4gICAgICAvLyBJZiB0aGUgc2Vzc2lvbiBpcyBub3QgaW4gdGhlIGNhY2hlLCBpdCBoYXMgYWxyZWFkeSBiZWVuIGRlbGV0ZWQuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc2Vzc2lvbkNhY2hlLnNldChcbiAgICAgIGF1dGhvcml0eSxcbiAgICAgIGV4aXN0aW5nU2Vzc2lvbnMuZmlsdGVyKChzKSA9PiBzICE9PSBzZXNzaW9uKVxuICAgICk7XG4gIH1cbn1cbiJdfQ==

@@ -18,2 +18,9 @@ import { HttpHandler, HttpRequest, HttpResponse } from "@aws-sdk/protocol-http";

sessionTimeout?: number;
/**
* Disables processing concurrent streams on a ClientHttp2Session instance. When set
* to true, the handler will create a new session instance for each request to a URL.
* **Default:** false.
* https://nodejs.org/api/http2.html#http2_class_clienthttp2session
*/
disableConcurrentStreams?: boolean;
}

@@ -23,7 +30,8 @@ export declare class NodeHttp2Handler implements HttpHandler {

private readonly sessionTimeout?;
private readonly connectionPool;
private readonly disableConcurrentStreams?;
readonly metadata: {
handlerProtocol: string;
};
constructor({ requestTimeout, sessionTimeout }?: NodeHttp2HandlerOptions);
private sessionCache;
constructor({ requestTimeout, sessionTimeout, disableConcurrentStreams }?: NodeHttp2HandlerOptions);
destroy(): void;

@@ -33,10 +41,21 @@ handle(request: HttpRequest, { abortSignal }?: HttpHandlerOptions): Promise<{

}>;
private getSession;
/**
* Destroy a session immediately and remove it from the http2 pool.
* Returns a session for the given URL.
*
* This check ensures that the session is only closed once
* and that an event on one session does not close a different session.
* @param authority The URL to create a session for.
* @param disableConcurrentStreams If true, a new session will be created for each request.
* @returns A session for the given URL.
*/
private getSession;
/**
* Destroys a session.
* @param session The session to destroy.
*/
private destroySession;
/**
* Delete a session from the connection pool.
* @param authority The authority of the session to delete.
* @param session The session to delete.
*/
private deleteSessionFromCache;
}

@@ -18,2 +18,9 @@ import { HttpHandler, HttpRequest, HttpResponse } from "@aws-sdk/protocol-http";

sessionTimeout?: number;
/**
* Disables processing concurrent streams on a ClientHttp2Session instance. When set
* to true, the handler will create a new session instance for each request to a URL.
* **Default:** false.
* https://nodejs.org/api/http2.html#http2_class_clienthttp2session
*/
disableConcurrentStreams?: boolean;
}

@@ -23,7 +30,8 @@ export declare class NodeHttp2Handler implements HttpHandler {

private readonly sessionTimeout?;
private readonly connectionPool;
private readonly disableConcurrentStreams?;
readonly metadata: {
handlerProtocol: string;
};
constructor({ requestTimeout, sessionTimeout }?: NodeHttp2HandlerOptions);
private sessionCache;
constructor({ requestTimeout, sessionTimeout, disableConcurrentStreams }?: NodeHttp2HandlerOptions);
destroy(): void;

@@ -33,10 +41,21 @@ handle(request: HttpRequest, { abortSignal }?: HttpHandlerOptions): Promise<{

}>;
private getSession;
/**
* Destroy a session immediately and remove it from the http2 pool.
* Returns a session for the given URL.
*
* This check ensures that the session is only closed once
* and that an event on one session does not close a different session.
* @param authority The URL to create a session for.
* @param disableConcurrentStreams If true, a new session will be created for each request.
* @returns A session for the given URL.
*/
private getSession;
/**
* Destroys a session.
* @param session The session to destroy.
*/
private destroySession;
/**
* Delete a session from the connection pool.
* @param authority The authority of the session to delete.
* @param session The session to delete.
*/
private deleteSessionFromCache;
}
{
"name": "@aws-sdk/node-http-handler",
"version": "3.20.0",
"version": "3.21.0",
"description": "Provides a way to make requests",

@@ -5,0 +5,0 @@ "scripts": {

@@ -25,2 +25,10 @@ import { HttpHandler, HttpRequest, HttpResponse } from "@aws-sdk/protocol-http";

sessionTimeout?: number;
/**
* Disables processing concurrent streams on a ClientHttp2Session instance. When set
* to true, the handler will create a new session instance for each request to a URL.
* **Default:** false.
* https://nodejs.org/api/http2.html#http2_class_clienthttp2session
*/
disableConcurrentStreams?: boolean;
}

@@ -31,17 +39,19 @@

private readonly sessionTimeout?: number;
private readonly connectionPool: Map<string, ClientHttp2Session>;
private readonly disableConcurrentStreams?: boolean;
public readonly metadata = { handlerProtocol: "h2" };
private sessionCache: Map<string, ClientHttp2Session[]>;
constructor({ requestTimeout, sessionTimeout }: NodeHttp2HandlerOptions = {}) {
constructor({ requestTimeout, sessionTimeout, disableConcurrentStreams }: NodeHttp2HandlerOptions = {}) {
this.requestTimeout = requestTimeout;
this.sessionTimeout = sessionTimeout;
this.connectionPool = new Map<string, ClientHttp2Session>();
this.disableConcurrentStreams = disableConcurrentStreams;
this.sessionCache = new Map<string, ClientHttp2Session[]>();
}
destroy(): void {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_, http2Session] of this.connectionPool) {
http2Session.destroy();
for (const sessions of this.sessionCache.values()) {
sessions.forEach((session) => this.destroySession(session));
}
this.connectionPool.clear();
this.sessionCache.clear();
}

@@ -54,11 +64,9 @@

let fulfilled = false;
const reject = (err: Error) => {
fulfilled = true;
rejectOriginal(err);
};
// if the request was already aborted, prevent doing extra work
if (abortSignal?.aborted) {
fulfilled = true;
const abortError = new Error("Request aborted");
abortError.name = "AbortError";
reject(abortError);
rejectOriginal(abortError);
return;

@@ -68,6 +76,16 @@ }

const { hostname, method, port, protocol, path, query } = request;
const authority = `${protocol}//${hostname}${port ? `:${port}` : ""}`;
const session = this.getSession(authority, this.disableConcurrentStreams || false);
const reject = (err: Error) => {
if (this.disableConcurrentStreams) {
this.destroySession(session);
}
fulfilled = true;
rejectOriginal(err);
};
const queryString = buildQueryString(query || {});
// create the http2 request
const req = this.getSession(`${protocol}//${hostname}${port ? `:${port}` : ""}`).request({
const req = session.request({
...request.headers,

@@ -86,2 +104,8 @@ [constants.HTTP2_HEADER_PATH]: queryString ? `${path}?${queryString}` : path,

resolve({ response: httpResponse });
if (this.disableConcurrentStreams) {
// Gracefully closes the Http2Session, allowing any existing streams to complete
// on their own and preventing new Http2Stream instances from being created.
session.close();
this.deleteSessionFromCache(authority, session);
}
});

@@ -118,2 +142,5 @@

req.on("close", () => {
if (this.disableConcurrentStreams) {
session.destroy();
}
if (!fulfilled) {

@@ -123,2 +150,3 @@ reject(new Error("Unexpected error: http2 request did not get a response"));

});
writeRequestBody(req, request);

@@ -128,11 +156,20 @@ });

private getSession(authority: string): ClientHttp2Session {
const connectionPool = this.connectionPool;
const existingSession = connectionPool.get(authority);
if (existingSession) return existingSession;
/**
* Returns a session for the given URL.
*
* @param authority The URL to create a session for.
* @param disableConcurrentStreams If true, a new session will be created for each request.
* @returns A session for the given URL.
*/
private getSession(authority: string, disableConcurrentStreams: boolean): ClientHttp2Session {
const sessionCache = this.sessionCache;
const existingSessions = sessionCache.get(authority) || [];
// If concurrent streams are not disabled, we can use the existing session.
if (existingSessions.length > 0 && !disableConcurrentStreams) return existingSessions[0];
const newSession = connect(authority);
connectionPool.set(authority, newSession);
const destroySessionCb = () => {
this.destroySession(authority, newSession);
this.destroySession(newSession);
this.deleteSessionFromCache(authority, newSession);
};

@@ -145,9 +182,8 @@ newSession.on("goaway", destroySessionCb);

if (sessionTimeout) {
newSession.setTimeout(sessionTimeout, () => {
if (connectionPool.get(authority) === newSession) {
newSession.close();
connectionPool.delete(authority);
}
});
newSession.setTimeout(sessionTimeout, destroySessionCb);
}
existingSessions.push(newSession);
sessionCache.set(authority, existingSessions);
return newSession;

@@ -157,16 +193,6 @@ }

/**
* Destroy a session immediately and remove it from the http2 pool.
*
* This check ensures that the session is only closed once
* and that an event on one session does not close a different session.
* Destroys a session.
* @param session The session to destroy.
*/
private destroySession(authority: string, session: ClientHttp2Session): void {
if (this.connectionPool.get(authority) !== session) {
// Already closed?
return;
}
this.connectionPool.delete(authority);
session.removeAllListeners("goaway");
session.removeAllListeners("error");
session.removeAllListeners("frameError");
private destroySession(session: ClientHttp2Session): void {
if (!session.destroyed) {

@@ -176,2 +202,19 @@ session.destroy();

}
/**
* Delete a session from the connection pool.
* @param authority The authority of the session to delete.
* @param session The session to delete.
*/
private deleteSessionFromCache(authority: string, session: ClientHttp2Session): void {
const existingSessions = this.sessionCache.get(authority) || [];
if (!existingSessions.includes(session)) {
// If the session is not in the cache, it has already been deleted.
return;
}
this.sessionCache.set(
authority,
existingSessions.filter((s) => s !== session)
);
}
}

@@ -1,2 +0,2 @@

import { HttpResponse } from "@aws-sdk/types";
import { HeaderBag, HttpResponse } from "@aws-sdk/types";
import { readFileSync } from "fs";

@@ -11,19 +11,32 @@ import { createServer as createHttpServer, IncomingMessage, Server as HttpServer, ServerResponse } from "http";

export function createResponseFunction(httpResp: HttpResponse) {
return function (request: IncomingMessage, response: ServerResponse) {
const setResponseHeaders = (response: ServerResponse, headers: HeaderBag) => {
for (const [key, value] of Object.entries(headers)) {
response.setHeader(key, value);
}
};
const setResponseBody = (response: ServerResponse, body: Readable | string) => {
if (body instanceof Readable) {
body.pipe(response);
} else {
response.end(body);
}
};
export const createResponseFunction =
(httpResp: HttpResponse) => (request: IncomingMessage, response: ServerResponse) => {
response.statusCode = httpResp.statusCode;
for (const name of Object.keys(httpResp.headers)) {
const values = httpResp.headers[name];
response.setHeader(name, values);
}
if (httpResp.body instanceof Readable) {
httpResp.body.pipe(response);
} else {
response.end(httpResp.body);
}
setResponseHeaders(response, httpResp.headers);
setResponseBody(response, httpResp.body);
};
}
export function createContinueResponseFunction(httpResp: HttpResponse) {
return function (request: IncomingMessage, response: ServerResponse) {
export const createResponseFunctionWithDelay =
(httpResp: HttpResponse, delay: number) => (request: IncomingMessage, response: ServerResponse) => {
response.statusCode = httpResp.statusCode;
setResponseHeaders(response, httpResp.headers);
setTimeout(() => setResponseBody(response, httpResp.body), delay);
};
export const createContinueResponseFunction =
(httpResp: HttpResponse) => (request: IncomingMessage, response: ServerResponse) => {
response.writeContinue();

@@ -34,5 +47,4 @@ setTimeout(() => {

};
}
export function createMockHttpsServer(): HttpsServer {
export const createMockHttpsServer = (): HttpsServer => {
const server = createHttpsServer({

@@ -43,12 +55,12 @@ key: readFileSync(join(fixturesDir, "test-server-key.pem")),

return server;
}
};
export function createMockHttpServer(): HttpServer {
export const createMockHttpServer = (): HttpServer => {
const server = createHttpServer();
return server;
}
};
export function createMockHttp2Server(): Http2Server {
export const createMockHttp2Server = (): Http2Server => {
const server = createHttp2Server();
return server;
}
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc