@riddance/host
Version:
338 lines • 40.9 kB
JavaScript
import { hash } from 'node:crypto';
import { isIP } from 'node:net';
import { brotliCompress } from 'node:zlib';
import { measure } from '../context.js';
export async function executeRequest(log, context, handler, options, success) {
const isShallow = context.env.SHALLOW_KEY && options.headers?.['x-shallow'] === context.env.SHALLOW_KEY;
const includeBodyInLogs = !handler.config?.excludeBodyFromLogs;
const logRequest = includeBodyInLogs
? { method: handler.method, ...options }
: withoutRequestBody({ method: handler.method, ...options });
let enrichedLog = log.enrichReserved({ meta: context.meta, request: logRequest });
if (isShallow) {
enrichedLog.trace('Shallow request');
return {
headers: {},
status: 204,
};
}
enrichedLog.trace('Request BEGIN');
try {
let parsedUrl;
let pathSteps;
const req = {
rawUrl: options.uri,
get url() {
if (parsedUrl) {
return parsedUrl;
}
const url = new URL(this.rawUrl);
parsedUrl = {
// eslint-disable-next-line unicorn/no-null
__proto__: null,
hash: url.hash,
host: url.host,
hostname: url.hostname,
href: url.href,
origin: url.origin,
password: url.password,
pathname: url.pathname,
port: url.port,
protocol: url.protocol,
search: url.search,
get searchParams() {
return url.searchParams;
},
toJSON: () => url.toJSON(),
toString: () => url.toString(),
username: url.username,
pathStepAt: (index) => {
const steps = (pathSteps ??= url.pathname.split('/'));
const step = steps[index + 1];
if (!step) {
throw Object.assign(new RangeError(`Path does not have a step at index ${index}.`), {
rawUrl: this.rawUrl,
pathName: url.pathname,
steps: steps.slice(1),
});
}
return step;
},
};
return parsedUrl;
},
body: requestBody(options),
headers: options.headers ?? {},
};
const result = await measure(log.enrichReserved({ meta: context.meta }), 'execution', () => handler.entry({ ...context, log: enrichedLog }, req));
const response = resultToResponse(result, includeBodyInLogs);
if (context.signal.aborted) {
response.headers = {
'x-timeout': '1',
...response.headers,
};
}
enrichedLog = enrichedLog.enrichReserved({
response: {
status: response.status,
headers: response.headers,
body: response.logBody,
},
});
if (response.status < 300) {
enrichedLog.debug('Request END');
await success();
}
else {
enrichedLog.warn('Request END');
}
return await compressed(req.headers, eTagged(req.headers, response));
}
catch (e) {
try {
const response = errorToResponse(e);
enrichedLog = enrichedLog.enrichReserved({ response });
enrichedLog.error('Request END', e);
return response;
}
catch (convertError) {
enrichedLog.error('Could not convert exception to error response.', convertError);
return {
headers: {},
status: 500,
};
}
}
}
function resultToResponse(result, withLogBody) {
if (!result) {
return {
headers: {},
status: 204,
};
}
else if (typeof result === 'string') {
const logBody = withLogBody ? result : undefined;
return {
headers: {
'content-type': 'text/plain',
},
status: 200,
body: result,
logBody,
};
}
else {
if (result.body === undefined) {
return {
headers: result.headers ?? {},
status: result.status ?? 200,
};
}
else if (typeof result.body === 'string') {
const logBody = withLogBody ? result.body : undefined;
return {
headers: withContentType(result.headers, 'text/plain'),
status: result.status ?? 200,
body: result.body,
logBody,
};
}
else if (Buffer.isBuffer(result.body)) {
const logBody = withLogBody ? result.body.toString('base64') : undefined;
return {
headers: withContentType(result.headers, 'application/octet-stream'),
status: result.status ?? 200,
body: result.body,
logBody,
};
}
else {
const logBody = withLogBody ? result.body : undefined;
return {
headers: withContentType(result.headers, 'application/json'),
status: result.status ?? 200,
body: JSON.stringify(result.body),
logBody,
};
}
}
}
function withoutRequestBody(options) {
if ('json' in options) {
const { json, ...bodyless } = options;
return bodyless;
}
if ('body' in options) {
const { body, ...bodyless } = options;
return bodyless;
}
return options;
}
function requestBody(options) {
if ('json' in options) {
return options.json;
}
if ('body' in options) {
return options.body;
}
return undefined;
}
function withContentType(headers, contentType) {
if (!headers) {
return {
'content-type': contentType,
};
}
headers['content-type'] ??= contentType;
return headers;
}
function errorToResponse(e) {
const { body, statusCode: status } = e;
if (typeof body === 'string') {
return {
headers: {
'content-type': 'text/plain',
},
status: status ?? 500,
body,
};
}
else if (typeof body === 'object') {
return {
headers: {
'content-type': 'application/json',
},
status: status ?? 500,
body: JSON.stringify(body),
};
}
else {
return {
headers: {},
status: status ?? 500,
};
}
}
export function clientFromHeaders(headers) {
if (!headers) {
return {};
}
return {
operationId: headers['x-request-id'] ?? headers['request-id'],
clientId: headers['x-client-id'] ??
headers['x-installation-id'] ??
headers['client-id'] ??
headers['installation-id'],
...clientAddress(headers),
userAgent: headers['x-forwarded-for-user-agent'] ?? headers['user-agent'],
};
}
function clientAddress(headers) {
const xff = headers['x-forwarded-for'];
if (!xff) {
return undefined;
}
for (const a of xff.split(',')) {
const valid = validClientAddress(a.trim());
if (valid) {
return valid;
}
}
return undefined;
}
function validClientAddress(s) {
const version = isIP(s);
if (version === 4) {
return { clientIp: s };
}
if (version === 6) {
return normalizedIp6(s);
}
if (s.startsWith('[') && s.endsWith(']')) {
return normalizedIp6(s.slice(1, -1));
}
if (s.startsWith(':')) {
const clientPort = Number(s.slice(1));
if (Number.isFinite(clientPort)) {
return { clientPort };
}
return undefined;
}
const url = `ip://${s}/`;
if (URL.canParse(url)) {
return addressFromUrl(new URL(url));
}
return undefined;
}
function normalizedIp6(s) {
const mapped = mappedAddress(s);
if (mapped) {
return { clientIp: mapped };
}
const url = new URL(`ip://[${s}]/`);
return { clientIp: url.hostname.slice(1, -1) };
}
function addressFromUrl(url) {
const clientIp = url.hostname.startsWith('[') && url.hostname.endsWith(']')
? url.hostname.slice(1, -1)
: url.hostname;
const clientPort = url.port ? Number(url.port) : undefined;
if (isIP(clientIp)) {
return {
clientIp,
clientPort,
};
}
return undefined;
}
function mappedAddress(s) {
if (s.startsWith('::ffff:')) {
const ip4 = s.slice(7);
if (isIP(ip4) === 4) {
return ip4;
}
}
return undefined;
}
function eTagged(requestHeaders, response) {
if (response.headers.etag || !response.body) {
return response;
}
const etag = hash('sha1', response.body, 'base64').slice(0, -1);
response.headers.etag = etag;
if (requestHeaders['if-none-match'] === etag) {
response.status = 304;
delete response.body;
}
return response;
}
async function compressed(requestHeaders, response) {
if (!response.body || response.body.length < 32_768 || response.headers['content-encoding']) {
return response;
}
const encodings = requestHeaders['accept-encoding']?.split(',').map(e => e.trim());
if (!encodings?.includes('br')) {
return response;
}
return {
status: response.status,
headers: {
'content-encoding': 'br',
...response.headers,
},
body: await compress(response.body),
};
}
function compress(body) {
return new Promise((resolve, reject) => {
brotliCompress(body, {}, (error, result) => {
if (error) {
reject(error);
return;
}
resolve(result);
});
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImh0dHAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUNsQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBQy9CLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDMUMsT0FBTyxFQUFXLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQTBCaEQsTUFBTSxDQUFDLEtBQUssVUFBVSxjQUFjLENBQ2hDLEdBQWUsRUFDZixPQUE2QixFQUM3QixPQUFvQixFQUNwQixPQUF1QixFQUN2QixPQUErQjtJQUUvQixNQUFNLFNBQVMsR0FDWCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsV0FBVyxDQUFDLEtBQUssT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUE7SUFDekYsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsbUJBQW1CLENBQUE7SUFDOUQsTUFBTSxVQUFVLEdBQUcsaUJBQWlCO1FBQ2hDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFLEdBQUcsT0FBTyxFQUFFO1FBQ3hDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUNoRSxJQUFJLFdBQVcsR0FBRyxHQUFHLENBQUMsY0FBYyxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUE7SUFDakYsSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUNaLFdBQVcsQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQTtRQUNwQyxPQUFPO1lBQ0gsT0FB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QTtJQUNuQixDQUFDO0lBQ0QsT0FBTztRQUNILE1BQU0sRUFBRSxRQUFRLENBQUMsTUFBTTtRQUN2QixPQUFPLEVBQUU7WUFDTCxrQkFBa0IsRUFBRSxJQUFJO1lBQ3hCLEdBQUcsUUFBUSxDQUFDLE9BQU87U0FDdEI7UUFDRCxJQUFJLEVBQUUsTUFBTSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztLQUN0QyxDQUFBO0FBQ0wsQ0FBQztBQUVELFNBQVMsUUFBUSxDQUFDLElBQXFCO0lBQ25DLE9BQU8sSUFBSSxPQUFPLENBQVMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDM0MsY0FBYyxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDdkMsSUFBSSxLQUFLLEVBQUUsQ0FBQztnQkFDUixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUE7Z0JBQ2IsT0FBTTtZQUNWLENBQUM7WUFDRCxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDbkIsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDLENBQUMsQ0FBQTtBQUNOLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBoYXNoIH0gZnJvbSAnbm9kZTpjcnlwdG8nXG5pbXBvcnQgeyBpc0lQIH0gZnJvbSAnbm9kZTpuZXQnXG5pbXBvcnQgeyBicm90bGlDb21wcmVzcyB9IGZyb20gJ25vZGU6emxpYidcbmltcG9ydCB7IENvbnRleHQsIG1lYXN1cmUgfSBmcm9tICcuLi9jb250ZXh0LmpzJ1xuaW1wb3J0IHR5cGUgeyBKc29uLCBQYXJzZWRVcmwsIFJlc3BvbnNlSGVhZGVycywgUmVzdWx0IH0gZnJvbSAnLi4vaHR0cC5qcydcbmltcG9ydCB7IENsaWVudEluZm8sIFJvb3RMb2dnZXIgfSBmcm9tICcuL2NvbnRleHQuanMnXG5pbXBvcnQgdHlwZSB7IEh0dHBIYW5kbGVyIH0gZnJvbSAnLi9odHRwLXJlZ2lzdHJ5LmpzJ1xuXG5leHBvcnQgdHlwZSBSZXNwb25zZSA9IHtcbiAgICBoZWFkZXJzOiB7IHJlYWRvbmx5IFtrZXk6IHN0cmluZ106IHN0cmluZyB9XG4gICAgc3RhdHVzOiBudW1iZXJcbiAgICBib2R5Pzogc3RyaW5nIHwgQnVmZmVyXG59XG5cbnR5cGUgUmVxdWVzdE9wdGlvbnMgPSBCb2R5bGVzc1JlcXVlc3RPcHRpb25zIHwgU3RyaW5nUmVxdWVzdE9wdGlvbnMgfCBKc29uUmVxdWVzdE9wdGlvbnNcblxudHlwZSBCb2R5bGVzc1JlcXVlc3RPcHRpb25zID0ge1xuICAgIHVyaTogc3RyaW5nXG4gICAgaGVhZGVycz86IHsgcmVhZG9ubHkgW2tleTogc3RyaW5nXTogc3RyaW5nIH1cbn1cblxudHlwZSBTdHJpbmdSZXF1ZXN0T3B0aW9ucyA9IEJvZHlsZXNzUmVxdWVzdE9wdGlvbnMgJiB7XG4gICAgYm9keTogc3RyaW5nXG59XG5cbnR5cGUgSnNvblJlcXVlc3RPcHRpb25zID0gQm9keWxlc3NSZXF1ZXN0T3B0aW9ucyAmIHtcbiAgICBqc29uOiBKc29uXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBleGVjdXRlUmVxdWVzdChcbiAgICBsb2c6IFJvb3RMb2dnZXIsXG4gICAgY29udGV4dDogT21pdDxDb250ZXh0LCAnbG9nJz4sXG4gICAgaGFuZGxlcjogSHR0cEhhbmRsZXIsXG4gICAgb3B0aW9uczogUmVxdWVzdE9wdGlvbnMsXG4gICAgc3VjY2VzczogKCkgPT4gUHJvbWlzZTx1bmtub3duPixcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgICBjb25zdCBpc1NoYWxsb3cgPVxuICAgICAgICBjb250ZXh0LmVudi5TSEFMTE9XX0tFWSAmJiBvcHRpb25zLmhlYWRlcnM/LlsneC1zaGFsbG93J10gPT09IGNvbnRleHQuZW52LlNIQUxMT1dfS0VZXG4gICAgY29uc3QgaW5jbHVkZUJvZHlJbkxvZ3MgPSAhaGFuZGxlci5jb25maWc/LmV4Y2x1ZGVCb2R5RnJvbUxvZ3NcbiAgICBjb25zdCBsb2dSZXF1ZXN0ID0gaW5jbHVkZUJvZHlJbkxvZ3NcbiAgICAgICAgPyB7IG1ldGhvZDogaGFuZGxlci5tZXRob2QsIC4uLm9wdGlvbnMgfVxuICAgICAgICA6IHdpdGhvdXRSZXF1ZXN0Qm9keSh7IG1ldGhvZDogaGFuZGxlci5tZXRob2QsIC4uLm9wdGlvbnMgfSlcbiAgICBsZXQgZW5yaWNoZWRMb2cgPSBsb2cuZW5yaWNoUmVzZXJ2ZWQoeyBtZXRhOiBjb250ZXh0Lm1ldGEsIHJlcXVlc3Q6IGxvZ1JlcXVlc3QgfSlcbiAgICBpZiAoaXNTaGFsbG93KSB7XG4gICAgICAgIGVucmljaGVkTG9nLnRyYWNlKCdTaGFsbG93IHJlcXVlc3QnKVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaGVhZGVyczoge30sXG4gICAgICAgICAgICBzdGF0dXM6IDIwNCxcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbnJpY2hlZExvZy50cmFjZSgnUmVxdWVzdCBCRUdJTicpXG4gICAgdHJ5IHtcbiAgICAgICAgbGV0IHBhcnNlZFVybDpcbiAgICAgICAgICAgIHwgKFBhcnNlZFVybCAmIHtcbiAgICAgICAgICAgICAgICAgIC8qKiBAaWdub3JlICovXG4gICAgICAgICAgICAgICAgICBfX3Byb3RvX186IHVua25vd25cbiAgICAgICAgICAgICAgICAgIC8qKiBAaWdub3JlICovXG4gICAgICAgICAgICAgICAgICB0b1N0cmluZzogKCkgPT4gc3RyaW5nXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB8IHVuZGVmaW5lZFxuICAgICAgICBsZXQgcGF0aFN0ZXBzOiBzdHJpbmdbXSB8IHVuZGVmaW5lZFxuICAgICAgICBjb25zdCByZXEgPSB7XG4gICAgICAgICAgICByYXdVcmw6IG9wdGlvbnMudXJpLFxuICAgICAgICAgICAgZ2V0IHVybCgpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFyc2VkVXJsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZWRVcmxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgdXJsID0gbmV3IFVSTCh0aGlzLnJhd1VybClcbiAgICAgICAgICAgICAgICBwYXJzZWRVcmwgPSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSB1bmljb3JuL25vLW51bGxcbiAgICAgICAgICAgICAgICAgICAgX19wcm90b19fOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICBoYXNoOiB1cmwuaGFzaCxcbiAgICAgICAgICAgICAgICAgICAgaG9zdDogdXJsLmhvc3QsXG4gICAgICAgICAgICAgICAgICAgIGhvc3RuYW1lOiB1cmwuaG9zdG5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGhyZWY6IHVybC5ocmVmLFxuICAgICAgICAgICAgICAgICAgICBvcmlnaW46IHVybC5vcmlnaW4sXG4gICAgICAgICAgICAgICAgICAgIHBhc3N3b3JkOiB1cmwucGFzc3dvcmQsXG4gICAgICAgICAgICAgICAgICAgIHBhdGhuYW1lOiB1cmwucGF0aG5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHBvcnQ6IHVybC5wb3J0LFxuICAgICAgICAgICAgICAgICAgICBwcm90b2NvbDogdXJsLnByb3RvY29sLFxuICAgICAgICAgICAgICAgICAgICBzZWFyY2g6IHVybC5zZWFyY2gsXG4gICAgICAgICAgICAgICAgICAgIGdldCBzZWFyY2hQYXJhbXMoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdXJsLnNlYXJjaFBhcmFtc1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB0b0pTT046ICgpID0+IHVybC50b0pTT04oKSxcbiAgICAgICAgICAgICAgICAgICAgdG9TdHJpbmc6ICgpID0+IHVybC50b1N0cmluZygpLFxuICAgICAgICAgICAgICAgICAgICB1c2VybmFtZTogdXJsLnVzZXJuYW1lLFxuICAgICAgICAgICAgICAgICAgICBwYXRoU3RlcEF0OiAoaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RlcHMgPSAocGF0aFN0ZXBzID8/PSB1cmwucGF0aG5hbWUuc3BsaXQoJy8nKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ZXAgPSBzdGVwc1tpbmRleCArIDFdXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXN0ZXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBPYmplY3QuYXNzaWduKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgUmFuZ2VFcnJvcihgUGF0aCBkb2VzIG5vdCBoYXZlIGEgc3RlcCBhdCBpbmRleCAke2luZGV4fS5gKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3VXJsOiB0aGlzLnJhd1VybCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGhOYW1lOiB1cmwucGF0aG5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwczogc3RlcHMuc2xpY2UoMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0ZXBcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlZFVybFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJvZHk6IHJlcXVlc3RCb2R5KG9wdGlvbnMpLFxuICAgICAgICAgICAgaGVhZGVyczogb3B0aW9ucy5oZWFkZXJzID8/IHt9LFxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbWVhc3VyZShsb2cuZW5yaWNoUmVzZXJ2ZWQoeyBtZXRhOiBjb250ZXh0Lm1ldGEgfSksICdleGVjdXRpb24nLCAoKSA9PlxuICAgICAgICAgICAgaGFuZGxlci5lbnRyeSh7IC4uLmNvbnRleHQsIGxvZzogZW5yaWNoZWRMb2cgfSwgcmVxKSxcbiAgICAgICAgKVxuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gcmVzdWx0VG9SZXNwb25zZShyZXN1bHQsIGluY2x1ZGVCb2R5SW5Mb2dzKVxuXG4gICAgICAgIGlmIChjb250ZXh0LnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICAgICAgICByZXNwb25zZS5oZWFkZXJzID0ge1xuICAgICAgICAgICAgICAgICd4LXRpbWVvdXQnOiAnMScsXG4gICAgICAgICAgICAgICAgLi4ucmVzcG9uc2UuaGVhZGVycyxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGVucmljaGVkTG9nID0gZW5yaWNoZWRMb2cuZW5yaWNoUmVzZXJ2ZWQoe1xuICAgICAgICAgICAgcmVzcG9uc2U6IHtcbiAgICAgICAgICAgICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgICAgICAgICAgICBoZWFkZXJzOiByZXNwb25zZS5oZWFkZXJzLFxuICAgICAgICAgICAgICAgIGJvZHk6IHJlc3BvbnNlLmxvZ0JvZHksXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzIDwgMzAwKSB7XG4gICAgICAgICAgICBlbnJpY2hlZExvZy5kZWJ1ZygnUmVxdWVzdCBFTkQnKVxuICAgICAgICAgICAgYXdhaXQgc3VjY2VzcygpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbnJpY2hlZExvZy53YXJuKCdSZXF1ZXN0IEVORCcpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IGNvbXByZXNzZWQocmVxLmhlYWRlcnMsIGVUYWdnZWQocmVxLmhlYWRlcnMsIHJlc3BvbnNlKSlcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGVycm9yVG9SZXNwb25zZShlKVxuICAgICAgICAgICAgZW5yaWNoZWRMb2cgPSBlbnJpY2hlZExvZy5lbnJpY2hSZXNlcnZlZCh7IHJlc3BvbnNlIH0pXG4gICAgICAgICAgICBlbnJpY2hlZExvZy5lcnJvcignUmVxdWVzdCBFTkQnLCBlKVxuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlXG4gICAgICAgIH0gY2F0Y2ggKGNvbnZlcnRFcnJvcikge1xuICAgICAgICAgICAgZW5yaWNoZWRMb2cuZXJyb3IoJ0NvdWxkIG5vdCBjb252ZXJ0IGV4Y2VwdGlvbiB0byBlcnJvciByZXNwb25zZS4nLCBjb252ZXJ0RXJyb3IpXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICAgICAgICAgIHN0YXR1czogNTAwLFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZXN1bHRUb1Jlc3BvbnNlKHJlc3VsdDogUmVzdWx0LCB3aXRoTG9nQm9keTogYm9vbGVhbik6IFJlc3BvbnNlICYgeyBsb2dCb2R5PzogdW5rbm93biB9IHtcbiAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaGVhZGVyczoge30sXG4gICAgICAgICAgICBzdGF0dXM6IDIwNCxcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIHJlc3VsdCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc3QgbG9nQm9keSA9IHdpdGhMb2dCb2R5ID8gcmVzdWx0IDogdW5kZWZpbmVkXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgJ2NvbnRlbnQtdHlwZSc6ICd0ZXh0L3BsYWluJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdGF0dXM6IDIwMCxcbiAgICAgICAgICAgIGJvZHk6IHJlc3VsdCxcbiAgICAgICAgICAgIGxvZ0JvZHksXG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAocmVzdWx0LmJvZHkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBoZWFkZXJzOiByZXN1bHQuaGVhZGVycyA/PyB7fSxcbiAgICAgICAgICAgICAgICBzdGF0dXM6IHJlc3VsdC5zdGF0dXMgPz8gMjAwLFxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiByZXN1bHQuYm9keSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNvbnN0IGxvZ0JvZHkgPSB3aXRoTG9nQm9keSA/IHJlc3VsdC5ib2R5IDogdW5kZWZpbmVkXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHdpdGhDb250ZW50VHlwZShyZXN1bHQuaGVhZGVycywgJ3RleHQvcGxhaW4nKSxcbiAgICAgICAgICAgICAgICBzdGF0dXM6IHJlc3VsdC5zdGF0dXMgPz8gMjAwLFxuICAgICAgICAgICAgICAgIGJvZHk6IHJlc3VsdC5ib2R5LFxuICAgICAgICAgICAgICAgIGxvZ0JvZHksXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoQnVmZmVyLmlzQnVmZmVyKHJlc3VsdC5ib2R5KSkge1xuICAgICAgICAgICAgY29uc3QgbG9nQm9keSA9IHdpdGhMb2dCb2R5ID8gcmVzdWx0LmJvZHkudG9TdHJpbmcoJ2Jhc2U2NCcpIDogdW5kZWZpbmVkXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHdpdGhDb250ZW50VHlwZShyZXN1bHQuaGVhZGVycywgJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScpLFxuICAgICAgICAgICAgICAgIHN0YXR1czogcmVzdWx0LnN0YXR1cyA/PyAyMDAsXG4gICAgICAgICAgICAgICAgYm9keTogcmVzdWx0LmJvZHksXG4gICAgICAgICAgICAgICAgbG9nQm9keSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGxvZ0JvZHkgPSB3aXRoTG9nQm9keSA/IHJlc3VsdC5ib2R5IDogdW5kZWZpbmVkXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGhlYWRlcnM6IHdpdGhDb250ZW50VHlwZShyZXN1bHQuaGVhZGVycywgJ2FwcGxpY2F0aW9uL2pzb24nKSxcbiAgICAgICAgICAgICAgICBzdGF0dXM6IHJlc3VsdC5zdGF0dXMgPz8gMjAwLFxuICAgICAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHJlc3VsdC5ib2R5KSxcbiAgICAgICAgICAgICAgICBsb2dCb2R5LFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiB3aXRob3V0UmVxdWVzdEJvZHkob3B0aW9uczogUmVxdWVzdE9wdGlvbnMgJiB7IG1ldGhvZDogc3RyaW5nIH0pIHtcbiAgICBpZiAoJ2pzb24nIGluIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgeyBqc29uLCAuLi5ib2R5bGVzcyB9ID0gb3B0aW9uc1xuICAgICAgICByZXR1cm4gYm9keWxlc3NcbiAgICB9XG4gICAgaWYgKCdib2R5JyBpbiBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHsgYm9keSwgLi4uYm9keWxlc3MgfSA9IG9wdGlvbnNcbiAgICAgICAgcmV0dXJuIGJvZHlsZXNzXG4gICAgfVxuICAgIHJldHVybiBvcHRpb25zXG59XG5cbmZ1bmN0aW9uIHJlcXVlc3RCb2R5KG9wdGlvbnM6IFJlcXVlc3RPcHRpb25zKTogSnNvbiB8IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCdqc29uJyBpbiBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLmpzb25cbiAgICB9XG4gICAgaWYgKCdib2R5JyBpbiBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLmJvZHlcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiB3aXRoQ29udGVudFR5cGUoaGVhZGVyczogUmVzcG9uc2VIZWFkZXJzIHwgdW5kZWZpbmVkLCBjb250ZW50VHlwZTogc3RyaW5nKSB7XG4gICAgaWYgKCFoZWFkZXJzKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAnY29udGVudC10eXBlJzogY29udGVudFR5cGUsXG4gICAgICAgIH1cbiAgICB9XG4gICAgaGVhZGVyc1snY29udGVudC10eXBlJ10gPz89IGNvbnRlbnRUeXBlXG4gICAgcmV0dXJuIGhlYWRlcnNcbn1cblxuZnVuY3Rpb24gZXJyb3JUb1Jlc3BvbnNlKGU6IHVua25vd24pOiBSZXNwb25zZSB7XG4gICAgY29uc3QgeyBib2R5LCBzdGF0dXNDb2RlOiBzdGF0dXMgfSA9IGUgYXMgeyBib2R5PzogdW5rbm93bjsgc3RhdHVzQ29kZT86IG51bWJlciB9XG4gICAgaWYgKHR5cGVvZiBib2R5ID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgICdjb250ZW50LXR5cGUnOiAndGV4dC9wbGFpbicsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3RhdHVzOiBzdGF0dXMgPz8gNTAwLFxuICAgICAgICAgICAgYm9keSxcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGJvZHkgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgJ2NvbnRlbnQtdHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdGF0dXM6IHN0YXR1cyA/PyA1MDAsXG4gICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KSxcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICAgICAgICAgIHN0YXR1czogc3RhdHVzID8/IDUwMCxcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsaWVudEZyb21IZWFkZXJzKFxuICAgIGhlYWRlcnM6IHsgcmVhZG9ubHkgW2tleTogc3RyaW5nXTogc3RyaW5nIHwgdW5kZWZpbmVkIH0gfCB1bmRlZmluZWQsXG4pOiBDbGllbnRJbmZvIHtcbiAgICBpZiAoIWhlYWRlcnMpIHtcbiAgICAgICAgcmV0dXJuIHt9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIG9wZXJhdGlvbklkOiBoZWFkZXJzWyd4LXJlcXVlc3QtaWQnXSA/PyBoZWFkZXJzWydyZXF1ZXN0LWlkJ10sXG4gICAgICAgIGNsaWVudElkOlxuICAgICAgICAgICAgaGVhZGVyc1sneC1jbGllbnQtaWQnXSA/P1xuICAgICAgICAgICAgaGVhZGVyc1sneC1pbnN0YWxsYXRpb24taWQnXSA/P1xuICAgICAgICAgICAgaGVhZGVyc1snY2xpZW50LWlkJ10gPz9cbiAgICAgICAgICAgIGhlYWRlcnNbJ2luc3RhbGxhdGlvbi1pZCddLFxuICAgICAgICAuLi5jbGllbnRBZGRyZXNzKGhlYWRlcnMpLFxuICAgICAgICB1c2VyQWdlbnQ6IGhlYWRlcnNbJ3gtZm9yd2FyZGVkLWZvci11c2VyLWFnZW50J10gPz8gaGVhZGVyc1sndXNlci1hZ2VudCddLFxuICAgIH1cbn1cblxuZnVuY3Rpb24gY2xpZW50QWRkcmVzcyhoZWFkZXJzOiB7IHJlYWRvbmx5IFtrZXk6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9KSB7XG4gICAgY29uc3QgeGZmID0gaGVhZGVyc1sneC1mb3J3YXJkZWQtZm9yJ11cbiAgICBpZiAoIXhmZikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkXG4gICAgfVxuICAgIGZvciAoY29uc3QgYSBvZiB4ZmYuc3BsaXQoJywnKSkge1xuICAgICAgICBjb25zdCB2YWxpZCA9IHZhbGlkQ2xpZW50QWRkcmVzcyhhLnRyaW0oKSlcbiAgICAgICAgaWYgKHZhbGlkKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsaWRcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkXG59XG5cbmZ1bmN0aW9uIHZhbGlkQ2xpZW50QWRkcmVzcyhzOiBzdHJpbmcpIHtcbiAgICBjb25zdCB2ZXJzaW9uID0gaXNJUChzKVxuICAgIGlmICh2ZXJzaW9uID09PSA0KSB7XG4gICAgICAgIHJldHVybiB7IGNsaWVudElwOiBzIH1cbiAgICB9XG4gICAgaWYgKHZlcnNpb24gPT09IDYpIHtcbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRJcDYocylcbiAgICB9XG4gICAgaWYgKHMuc3RhcnRzV2l0aCgnWycpICYmIHMuZW5kc1dpdGgoJ10nKSkge1xuICAgICAgICByZXR1cm4gbm9ybWFsaXplZElwNihzLnNsaWNlKDEsIC0xKSlcbiAgICB9XG4gICAgaWYgKHMuc3RhcnRzV2l0aCgnOicpKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudFBvcnQgPSBOdW1iZXIocy5zbGljZSgxKSlcbiAgICAgICAgaWYgKE51bWJlci5pc0Zpbml0ZShjbGllbnRQb3J0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgY2xpZW50UG9ydCB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZFxuICAgIH1cbiAgICBjb25zdCB1cmwgPSBgaXA6Ly8ke3N9L2BcbiAgICBpZiAoVVJMLmNhblBhcnNlKHVybCkpIHtcbiAgICAgICAgcmV0dXJuIGFkZHJlc3NGcm9tVXJsKG5ldyBVUkwodXJsKSlcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVkSXA2KHM6IHN0cmluZykge1xuICAgIGNvbnN0IG1hcHBlZCA9IG1hcHBlZEFkZHJlc3MocylcbiAgICBpZiAobWFwcGVkKSB7XG4gICAgICAgIHJldHVybiB7IGNsaWVudElwOiBtYXBwZWQgfVxuICAgIH1cbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGBpcDovL1ske3N9XS9gKVxuICAgIHJldHVybiB7IGNsaWVudElwOiB1cmwuaG9zdG5hbWUuc2xpY2UoMSwgLTEpIH1cbn1cblxuZnVuY3Rpb24gYWRkcmVzc0Zyb21VcmwodXJsOiBVUkwpIHtcbiAgICBjb25zdCBjbGllbnRJcCA9XG4gICAgICAgIHVybC5ob3N0bmFtZS5zdGFydHNXaXRoKCdbJykgJiYgdXJsLmhvc3RuYW1lLmVuZHNXaXRoKCddJylcbiAgICAgICAgICAgID8gdXJsLmhvc3RuYW1lLnNsaWNlKDEsIC0xKVxuICAgICAgICAgICAgOiB1cmwuaG9zdG5hbWVcbiAgICBjb25zdCBjbGllbnRQb3J0ID0gdXJsLnBvcnQgPyBOdW1iZXIodXJsLnBvcnQpIDogdW5kZWZpbmVkXG4gICAgaWYgKGlzSVAoY2xpZW50SXApKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjbGllbnRJcCxcbiAgICAgICAgICAgIGNsaWVudFBvcnQsXG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiBtYXBwZWRBZGRyZXNzKHM6IHN0cmluZykge1xuICAgIGlmIChzLnN0YXJ0c1dpdGgoJzo6ZmZmZjonKSkge1xuICAgICAgICBjb25zdCBpcDQgPSBzLnNsaWNlKDcpXG4gICAgICAgIGlmIChpc0lQKGlwNCkgPT09IDQpIHtcbiAgICAgICAgICAgIHJldHVybiBpcDRcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkXG59XG5cbmZ1bmN0aW9uIGVUYWdnZWQoXG4gICAgcmVxdWVzdEhlYWRlcnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0sXG4gICAgcmVzcG9uc2U6IFJlc3BvbnNlICYgeyBoZWFkZXJzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9IH0sXG4pOiBSZXNwb25zZSB7XG4gICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZXRhZyB8fCAhcmVzcG9uc2UuYm9keSkge1xuICAgICAgICByZXR1cm4gcmVzcG9uc2VcbiAgICB9XG4gICAgY29uc3QgZXRhZyA9IGhhc2goJ3NoYTEnLCByZXNwb25zZS5ib2R5LCAnYmFzZTY0Jykuc2xpY2UoMCwgLTEpXG4gICAgcmVzcG9uc2UuaGVhZGVycy5ldGFnID0gZXRhZ1xuICAgIGlmIChyZXF1ZXN0SGVhZGVyc1snaWYtbm9uZS1tYXRjaCddID09PSBldGFnKSB7XG4gICAgICAgIHJlc3BvbnNlLnN0YXR1cyA9IDMwNFxuICAgICAgICBkZWxldGUgcmVzcG9uc2UuYm9keVxuICAgIH1cbiAgICByZXR1cm4gcmVzcG9uc2Vcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29tcHJlc3NlZChcbiAgICByZXF1ZXN0SGVhZGVyczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSxcbiAgICByZXNwb25zZTogUmVzcG9uc2UgJiB7IGhlYWRlcnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gfSxcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgICBpZiAoIXJlc3BvbnNlLmJvZHkgfHwgcmVzcG9uc2UuYm9keS5sZW5ndGggPCAzMl83NjggfHwgcmVzcG9uc2UuaGVhZGVyc1snY29udGVudC1lbmNvZGluZyddKSB7XG4gICAgICAgIHJldHVybiByZXNwb25zZVxuICAgIH1cbiAgICBjb25zdCBlbmNvZGluZ3MgPSByZXF1ZXN0SGVhZGVyc1snYWNjZXB0LWVuY29kaW5nJ10/LnNwbGl0KCcsJykubWFwKGUgPT4gZS50cmltKCkpXG4gICAgaWYgKCFlbmNvZGluZ3M/LmluY2x1ZGVzKCdicicpKSB7XG4gICAgICAgIHJldHVybiByZXNwb25zZVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgJ2NvbnRlbnQtZW5jb2RpbmcnOiAnYnInLFxuICAgICAgICAgICAgLi4ucmVzcG9uc2UuaGVhZGVycyxcbiAgICAgICAgfSxcbiAgICAgICAgYm9keTogYXdhaXQgY29tcHJlc3MocmVzcG9uc2UuYm9keSksXG4gICAgfVxufVxuXG5mdW5jdGlvbiBjb21wcmVzcyhib2R5OiBzdHJpbmcgfCBCdWZmZXIpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8QnVmZmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGJyb3RsaUNvbXByZXNzKGJvZHksIHt9LCAoZXJyb3IsIHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKVxuICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHQpXG4gICAgICAgIH0pXG4gICAgfSlcbn1cbiJdfQ==