@angular/common
Version:
Angular - commonly needed directives and services
139 lines • 17.5 kB
JavaScript
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { APP_BOOTSTRAP_LISTENER, ApplicationRef, inject, InjectionToken, makeStateKey, TransferState, ɵENABLED_SSR_FEATURES as ENABLED_SSR_FEATURES } from '@angular/core';
import { of } from 'rxjs';
import { first, tap } from 'rxjs/operators';
import { HttpHeaders } from './headers';
import { HTTP_ROOT_INTERCEPTOR_FNS } from './interceptor';
import { HttpResponse } from './response';
const CACHE_STATE = new InjectionToken(ngDevMode ? 'HTTP_TRANSFER_STATE_CACHE_STATE' : '');
/**
* A list of allowed HTTP methods to cache.
*/
const ALLOWED_METHODS = ['GET', 'HEAD'];
export function transferCacheInterceptorFn(req, next) {
const { isCacheActive } = inject(CACHE_STATE);
// Stop using the cache if the application has stabilized, indicating initial rendering
// is complete.
if (!isCacheActive || !ALLOWED_METHODS.includes(req.method)) {
// Cache is no longer active or method is not HEAD or GET.
// Pass the request through.
return next(req);
}
const transferState = inject(TransferState);
const storeKey = makeCacheKey(req);
const response = transferState.get(storeKey, null);
if (response) {
// Request found in cache. Respond using it.
let body = response.body;
switch (response.responseType) {
case 'arraybuffer':
body = new TextEncoder().encode(response.body).buffer;
break;
case 'blob':
body = new Blob([response.body]);
break;
}
return of(new HttpResponse({
body,
headers: new HttpHeaders(response.headers),
status: response.status,
statusText: response.statusText,
url: response.url,
}));
}
// Request not found in cache. Make the request and cache it.
return next(req).pipe(tap((event) => {
if (event instanceof HttpResponse) {
transferState.set(storeKey, {
body: event.body,
headers: getHeadersMap(event.headers),
status: event.status,
statusText: event.statusText,
url: event.url || '',
responseType: req.responseType,
});
}
}));
}
function getHeadersMap(headers) {
const headersMap = {};
for (const key of headers.keys()) {
const values = headers.getAll(key);
if (values !== null) {
headersMap[key] = values;
}
}
return headersMap;
}
function makeCacheKey(request) {
// make the params encoded same as a url so it's easy to identify
const { params, method, responseType, url } = request;
const encodedParams = params.keys().sort().map((k) => `${k}=${params.getAll(k)}`).join('&');
const key = method + '.' + responseType + '.' + url + '?' + encodedParams;
const hash = generateHash(key);
return makeStateKey(hash);
}
/**
* A method that returns a hash representation of a string using a variant of DJB2 hash
* algorithm.
*
* This is the same hashing logic that is used to generate component ids.
*/
function generateHash(value) {
let hash = 0;
for (const char of value) {
hash = Math.imul(31, hash) + char.charCodeAt(0) << 0;
}
// Force positive number hash.
// 2147483647 = equivalent of Integer.MAX_VALUE.
hash += 2147483647 + 1;
return hash.toString();
}
/**
* Returns the DI providers needed to enable HTTP transfer cache.
*
* By default, when using server rendering, requests are performed twice: once on the server and
* other one on the browser.
*
* When these providers are added, requests performed on the server are cached and reused during the
* bootstrapping of the application in the browser thus avoiding duplicate requests and reducing
* load time.
*
*/
export function withHttpTransferCache() {
return [
{
provide: CACHE_STATE,
useFactory: () => {
inject(ENABLED_SSR_FEATURES).add('httpcache');
return { isCacheActive: true };
}
},
{
provide: HTTP_ROOT_INTERCEPTOR_FNS,
useValue: transferCacheInterceptorFn,
multi: true,
deps: [TransferState, CACHE_STATE]
},
{
provide: APP_BOOTSTRAP_LISTENER,
multi: true,
useFactory: () => {
const appRef = inject(ApplicationRef);
const cacheState = inject(CACHE_STATE);
return () => {
appRef.isStable.pipe(first((isStable) => isStable)).toPromise().then(() => {
cacheState.isCacheActive = false;
});
};
}
}
];
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXJfY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21tb24vaHR0cC9zcmMvdHJhbnNmZXJfY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLHNCQUFzQixFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBc0IsYUFBYSxFQUFFLHFCQUFxQixJQUFJLG9CQUFvQixFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQzdMLE9BQU8sRUFBYSxFQUFFLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDcEMsT0FBTyxFQUFDLEtBQUssRUFBRSxHQUFHLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUUxQyxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ3RDLE9BQU8sRUFBQyx5QkFBeUIsRUFBZ0IsTUFBTSxlQUFlLENBQUM7QUFFdkUsT0FBTyxFQUFZLFlBQVksRUFBQyxNQUFNLFlBQVksQ0FBQztBQVduRCxNQUFNLFdBQVcsR0FBRyxJQUFJLGNBQWMsQ0FDbEMsU0FBUyxDQUFDLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7QUFFeEQ7O0dBRUc7QUFDSCxNQUFNLGVBQWUsR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztBQUV4QyxNQUFNLFVBQVUsMEJBQTBCLENBQ3RDLEdBQXlCLEVBQUUsSUFBbUI7SUFDaEQsTUFBTSxFQUFDLGFBQWEsRUFBQyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUU1Qyx1RkFBdUY7SUFDdkYsZUFBZTtJQUNmLElBQUksQ0FBQyxhQUFhLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRTtRQUMzRCwwREFBMEQ7UUFDMUQsNEJBQTRCO1FBQzVCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0tBQ2xCO0lBRUQsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQzVDLE1BQU0sUUFBUSxHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUVuRCxJQUFJLFFBQVEsRUFBRTtRQUNaLDRDQUE0QztRQUM1QyxJQUFJLElBQUksR0FBc0MsUUFBUSxDQUFDLElBQUksQ0FBQztRQUU1RCxRQUFRLFFBQVEsQ0FBQyxZQUFZLEVBQUU7WUFDN0IsS0FBSyxhQUFhO2dCQUNoQixJQUFJLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDdEQsTUFBTTtZQUNSLEtBQUssTUFBTTtnQkFDVCxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDakMsTUFBTTtTQUNUO1FBRUQsT0FBTyxFQUFFLENBQ0wsSUFBSSxZQUFZLENBQUM7WUFDZixJQUFJO1lBQ0osT0FBTyxFQUFFLElBQUksV0FBVyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7WUFDMUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNO1lBQ3ZCLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVTtZQUMvQixHQUFHLEVBQUUsUUFBUSxDQUFDLEdBQUc7U0FDbEIsQ0FBQyxDQUNMLENBQUM7S0FDSDtJQUVELDZEQUE2RDtJQUM3RCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQ2pCLEdBQUcsQ0FBQyxDQUFDLEtBQXlCLEVBQUUsRUFBRTtRQUNoQyxJQUFJLEtBQUssWUFBWSxZQUFZLEVBQUU7WUFDakMsYUFBYSxDQUFDLEdBQUcsQ0FBdUIsUUFBUSxFQUFFO2dCQUNoRCxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7Z0JBQ2hCLE9BQU8sRUFBRSxhQUFhLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQztnQkFDckMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO2dCQUNwQixVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVU7Z0JBQzVCLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJLEVBQUU7Z0JBQ3BCLFlBQVksRUFBRSxHQUFHLENBQUMsWUFBWTthQUMvQixDQUFDLENBQUM7U0FDSjtJQUNILENBQUMsQ0FBQyxDQUNMLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsT0FBb0I7SUFDekMsTUFBTSxVQUFVLEdBQTZCLEVBQUUsQ0FBQztJQUVoRCxLQUFLLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUNoQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25DLElBQUksTUFBTSxLQUFLLElBQUksRUFBRTtZQUNuQixVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDO1NBQzFCO0tBQ0Y7SUFFRCxPQUFPLFVBQVUsQ0FBQztBQUNwQixDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsT0FBeUI7SUFDN0MsaUVBQWlFO0lBQ2pFLE1BQU0sRUFBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUMsR0FBRyxPQUFPLENBQUM7SUFDcEQsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzVGLE1BQU0sR0FBRyxHQUFHLE1BQU0sR0FBRyxHQUFHLEdBQUcsWUFBWSxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLGFBQWEsQ0FBQztJQUUxRSxNQUFNLElBQUksR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFL0IsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBUyxZQUFZLENBQUMsS0FBYTtJQUNqQyxJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7SUFFYixLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRTtRQUN4QixJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDdEQ7SUFFRCw4QkFBOEI7SUFDOUIsZ0RBQWdEO0lBQ2hELElBQUksSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBRXZCLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ3pCLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQjtJQUNuQyxPQUFPO1FBQ0w7WUFDRSxPQUFPLEVBQUUsV0FBVztZQUNwQixVQUFVLEVBQUUsR0FBRyxFQUFFO2dCQUNmLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDOUMsT0FBTyxFQUFDLGFBQWEsRUFBRSxJQUFJLEVBQUMsQ0FBQztZQUMvQixDQUFDO1NBQ0Y7UUFDRDtZQUNFLE9BQU8sRUFBRSx5QkFBeUI7WUFDbEMsUUFBUSxFQUFFLDBCQUEwQjtZQUNwQyxLQUFLLEVBQUUsSUFBSTtZQUNYLElBQUksRUFBRSxDQUFDLGFBQWEsRUFBRSxXQUFXLENBQUM7U0FDbkM7UUFDRDtZQUNFLE9BQU8sRUFBRSxzQkFBc0I7WUFDL0IsS0FBSyxFQUFFLElBQUk7WUFDWCxVQUFVLEVBQUUsR0FBRyxFQUFFO2dCQUNmLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDdEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUV2QyxPQUFPLEdBQUcsRUFBRTtvQkFDVixNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTt3QkFDeEUsVUFBVSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUM7b0JBQ25DLENBQUMsQ0FBQyxDQUFDO2dCQUNMLENBQUMsQ0FBQztZQUNKLENBQUM7U0FDRjtLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7QVBQX0JPT1RTVFJBUF9MSVNURU5FUiwgQXBwbGljYXRpb25SZWYsIGluamVjdCwgSW5qZWN0aW9uVG9rZW4sIG1ha2VTdGF0ZUtleSwgUHJvdmlkZXIsIFN0YXRlS2V5LCBUcmFuc2ZlclN0YXRlLCDJtUVOQUJMRURfU1NSX0ZFQVRVUkVTIGFzIEVOQUJMRURfU1NSX0ZFQVRVUkVTfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7T2JzZXJ2YWJsZSwgb2Z9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtmaXJzdCwgdGFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7SHR0cEhlYWRlcnN9IGZyb20gJy4vaGVhZGVycyc7XG5pbXBvcnQge0hUVFBfUk9PVF9JTlRFUkNFUFRPUl9GTlMsIEh0dHBIYW5kbGVyRm59IGZyb20gJy4vaW50ZXJjZXB0b3InO1xuaW1wb3J0IHtIdHRwUmVxdWVzdH0gZnJvbSAnLi9yZXF1ZXN0JztcbmltcG9ydCB7SHR0cEV2ZW50LCBIdHRwUmVzcG9uc2V9IGZyb20gJy4vcmVzcG9uc2UnO1xuXG5pbnRlcmZhY2UgVHJhbnNmZXJIdHRwUmVzcG9uc2Uge1xuICBib2R5OiBhbnk7XG4gIGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPjtcbiAgc3RhdHVzPzogbnVtYmVyO1xuICBzdGF0dXNUZXh0Pzogc3RyaW5nO1xuICB1cmw/OiBzdHJpbmc7XG4gIHJlc3BvbnNlVHlwZT86IEh0dHBSZXF1ZXN0PHVua25vd24+WydyZXNwb25zZVR5cGUnXTtcbn1cblxuY29uc3QgQ0FDSEVfU1RBVEUgPSBuZXcgSW5qZWN0aW9uVG9rZW48e2lzQ2FjaGVBY3RpdmU6IGJvb2xlYW59PihcbiAgICBuZ0Rldk1vZGUgPyAnSFRUUF9UUkFOU0ZFUl9TVEFURV9DQUNIRV9TVEFURScgOiAnJyk7XG5cbi8qKlxuICogQSBsaXN0IG9mIGFsbG93ZWQgSFRUUCBtZXRob2RzIHRvIGNhY2hlLlxuICovXG5jb25zdCBBTExPV0VEX01FVEhPRFMgPSBbJ0dFVCcsICdIRUFEJ107XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2ZlckNhY2hlSW50ZXJjZXB0b3JGbihcbiAgICByZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBuZXh0OiBIdHRwSGFuZGxlckZuKTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8dW5rbm93bj4+IHtcbiAgY29uc3Qge2lzQ2FjaGVBY3RpdmV9ID0gaW5qZWN0KENBQ0hFX1NUQVRFKTtcblxuICAvLyBTdG9wIHVzaW5nIHRoZSBjYWNoZSBpZiB0aGUgYXBwbGljYXRpb24gaGFzIHN0YWJpbGl6ZWQsIGluZGljYXRpbmcgaW5pdGlhbCByZW5kZXJpbmdcbiAgLy8gaXMgY29tcGxldGUuXG4gIGlmICghaXNDYWNoZUFjdGl2ZSB8fCAhQUxMT1dFRF9NRVRIT0RTLmluY2x1ZGVzKHJlcS5tZXRob2QpKSB7XG4gICAgLy8gQ2FjaGUgaXMgbm8gbG9uZ2VyIGFjdGl2ZSBvciBtZXRob2QgaXMgbm90IEhFQUQgb3IgR0VULlxuICAgIC8vIFBhc3MgdGhlIHJlcXVlc3QgdGhyb3VnaC5cbiAgICByZXR1cm4gbmV4dChyZXEpO1xuICB9XG5cbiAgY29uc3QgdHJhbnNmZXJTdGF0ZSA9IGluamVjdChUcmFuc2ZlclN0YXRlKTtcbiAgY29uc3Qgc3RvcmVLZXkgPSBtYWtlQ2FjaGVLZXkocmVxKTtcbiAgY29uc3QgcmVzcG9uc2UgPSB0cmFuc2ZlclN0YXRlLmdldChzdG9yZUtleSwgbnVsbCk7XG5cbiAgaWYgKHJlc3BvbnNlKSB7XG4gICAgLy8gUmVxdWVzdCBmb3VuZCBpbiBjYWNoZS4gUmVzcG9uZCB1c2luZyBpdC5cbiAgICBsZXQgYm9keTogQXJyYXlCdWZmZXJ8QmxvYnxzdHJpbmd8dW5kZWZpbmVkID0gcmVzcG9uc2UuYm9keTtcblxuICAgIHN3aXRjaCAocmVzcG9uc2UucmVzcG9uc2VUeXBlKSB7XG4gICAgICBjYXNlICdhcnJheWJ1ZmZlcic6XG4gICAgICAgIGJvZHkgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUocmVzcG9uc2UuYm9keSkuYnVmZmVyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Jsb2InOlxuICAgICAgICBib2R5ID0gbmV3IEJsb2IoW3Jlc3BvbnNlLmJvZHldKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9mKFxuICAgICAgICBuZXcgSHR0cFJlc3BvbnNlKHtcbiAgICAgICAgICBib2R5LFxuICAgICAgICAgIGhlYWRlcnM6IG5ldyBIdHRwSGVhZGVycyhyZXNwb25zZS5oZWFkZXJzKSxcbiAgICAgICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgICAgICBzdGF0dXNUZXh0OiByZXNwb25zZS5zdGF0dXNUZXh0LFxuICAgICAgICAgIHVybDogcmVzcG9uc2UudXJsLFxuICAgICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgLy8gUmVxdWVzdCBub3QgZm91bmQgaW4gY2FjaGUuIE1ha2UgdGhlIHJlcXVlc3QgYW5kIGNhY2hlIGl0LlxuICByZXR1cm4gbmV4dChyZXEpLnBpcGUoXG4gICAgICB0YXAoKGV2ZW50OiBIdHRwRXZlbnQ8dW5rbm93bj4pID0+IHtcbiAgICAgICAgaWYgKGV2ZW50IGluc3RhbmNlb2YgSHR0cFJlc3BvbnNlKSB7XG4gICAgICAgICAgdHJhbnNmZXJTdGF0ZS5zZXQ8VHJhbnNmZXJIdHRwUmVzcG9uc2U+KHN0b3JlS2V5LCB7XG4gICAgICAgICAgICBib2R5OiBldmVudC5ib2R5LFxuICAgICAgICAgICAgaGVhZGVyczogZ2V0SGVhZGVyc01hcChldmVudC5oZWFkZXJzKSxcbiAgICAgICAgICAgIHN0YXR1czogZXZlbnQuc3RhdHVzLFxuICAgICAgICAgICAgc3RhdHVzVGV4dDogZXZlbnQuc3RhdHVzVGV4dCxcbiAgICAgICAgICAgIHVybDogZXZlbnQudXJsIHx8ICcnLFxuICAgICAgICAgICAgcmVzcG9uc2VUeXBlOiByZXEucmVzcG9uc2VUeXBlLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KSxcbiAgKTtcbn1cblxuZnVuY3Rpb24gZ2V0SGVhZGVyc01hcChoZWFkZXJzOiBIdHRwSGVhZGVycyk6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiB7XG4gIGNvbnN0IGhlYWRlcnNNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHt9O1xuXG4gIGZvciAoY29uc3Qga2V5IG9mIGhlYWRlcnMua2V5cygpKSB7XG4gICAgY29uc3QgdmFsdWVzID0gaGVhZGVycy5nZXRBbGwoa2V5KTtcbiAgICBpZiAodmFsdWVzICE9PSBudWxsKSB7XG4gICAgICBoZWFkZXJzTWFwW2tleV0gPSB2YWx1ZXM7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGhlYWRlcnNNYXA7XG59XG5cbmZ1bmN0aW9uIG1ha2VDYWNoZUtleShyZXF1ZXN0OiBIdHRwUmVxdWVzdDxhbnk+KTogU3RhdGVLZXk8VHJhbnNmZXJIdHRwUmVzcG9uc2U+IHtcbiAgLy8gbWFrZSB0aGUgcGFyYW1zIGVuY29kZWQgc2FtZSBhcyBhIHVybCBzbyBpdCdzIGVhc3kgdG8gaWRlbnRpZnlcbiAgY29uc3Qge3BhcmFtcywgbWV0aG9kLCByZXNwb25zZVR5cGUsIHVybH0gPSByZXF1ZXN0O1xuICBjb25zdCBlbmNvZGVkUGFyYW1zID0gcGFyYW1zLmtleXMoKS5zb3J0KCkubWFwKChrKSA9PiBgJHtrfT0ke3BhcmFtcy5nZXRBbGwoayl9YCkuam9pbignJicpO1xuICBjb25zdCBrZXkgPSBtZXRob2QgKyAnLicgKyByZXNwb25zZVR5cGUgKyAnLicgKyB1cmwgKyAnPycgKyBlbmNvZGVkUGFyYW1zO1xuXG4gIGNvbnN0IGhhc2ggPSBnZW5lcmF0ZUhhc2goa2V5KTtcblxuICByZXR1cm4gbWFrZVN0YXRlS2V5KGhhc2gpO1xufVxuXG4vKipcbiAqIEEgbWV0aG9kIHRoYXQgcmV0dXJucyBhIGhhc2ggcmVwcmVzZW50YXRpb24gb2YgYSBzdHJpbmcgdXNpbmcgYSB2YXJpYW50IG9mIERKQjIgaGFzaFxuICogYWxnb3JpdGhtLlxuICpcbiAqIFRoaXMgaXMgdGhlIHNhbWUgaGFzaGluZyBsb2dpYyB0aGF0IGlzIHVzZWQgdG8gZ2VuZXJhdGUgY29tcG9uZW50IGlkcy5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVIYXNoKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgaGFzaCA9IDA7XG5cbiAgZm9yIChjb25zdCBjaGFyIG9mIHZhbHVlKSB7XG4gICAgaGFzaCA9IE1hdGguaW11bCgzMSwgaGFzaCkgKyBjaGFyLmNoYXJDb2RlQXQoMCkgPDwgMDtcbiAgfVxuXG4gIC8vIEZvcmNlIHBvc2l0aXZlIG51bWJlciBoYXNoLlxuICAvLyAyMTQ3NDgzNjQ3ID0gZXF1aXZhbGVudCBvZiBJbnRlZ2VyLk1BWF9WQUxVRS5cbiAgaGFzaCArPSAyMTQ3NDgzNjQ3ICsgMTtcblxuICByZXR1cm4gaGFzaC50b1N0cmluZygpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIERJIHByb3ZpZGVycyBuZWVkZWQgdG8gZW5hYmxlIEhUVFAgdHJhbnNmZXIgY2FjaGUuXG4gKlxuICogQnkgZGVmYXVsdCwgd2hlbiB1c2luZyBzZXJ2ZXIgcmVuZGVyaW5nLCByZXF1ZXN0cyBhcmUgcGVyZm9ybWVkIHR3aWNlOiBvbmNlIG9uIHRoZSBzZXJ2ZXIgYW5kXG4gKiBvdGhlciBvbmUgb24gdGhlIGJyb3dzZXIuXG4gKlxuICogV2hlbiB0aGVzZSBwcm92aWRlcnMgYXJlIGFkZGVkLCByZXF1ZXN0cyBwZXJmb3JtZWQgb24gdGhlIHNlcnZlciBhcmUgY2FjaGVkIGFuZCByZXVzZWQgZHVyaW5nIHRoZVxuICogYm9vdHN0cmFwcGluZyBvZiB0aGUgYXBwbGljYXRpb24gaW4gdGhlIGJyb3dzZXIgdGh1cyBhdm9pZGluZyBkdXBsaWNhdGUgcmVxdWVzdHMgYW5kIHJlZHVjaW5nXG4gKiBsb2FkIHRpbWUuXG4gKlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2l0aEh0dHBUcmFuc2ZlckNhY2hlKCk6IFByb3ZpZGVyW10ge1xuICByZXR1cm4gW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IENBQ0hFX1NUQVRFLFxuICAgICAgdXNlRmFjdG9yeTogKCkgPT4ge1xuICAgICAgICBpbmplY3QoRU5BQkxFRF9TU1JfRkVBVFVSRVMpLmFkZCgnaHR0cGNhY2hlJyk7XG4gICAgICAgIHJldHVybiB7aXNDYWNoZUFjdGl2ZTogdHJ1ZX07XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBIVFRQX1JPT1RfSU5URVJDRVBUT1JfRk5TLFxuICAgICAgdXNlVmFsdWU6IHRyYW5zZmVyQ2FjaGVJbnRlcmNlcHRvckZuLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgICBkZXBzOiBbVHJhbnNmZXJTdGF0ZSwgQ0FDSEVfU1RBVEVdXG4gICAgfSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBBUFBfQk9PVFNUUkFQX0xJU1RFTkVSLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgICB1c2VGYWN0b3J5OiAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGFwcFJlZiA9IGluamVjdChBcHBsaWNhdGlvblJlZik7XG4gICAgICAgIGNvbnN0IGNhY2hlU3RhdGUgPSBpbmplY3QoQ0FDSEVfU1RBVEUpO1xuXG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgYXBwUmVmLmlzU3RhYmxlLnBpcGUoZmlyc3QoKGlzU3RhYmxlKSA9PiBpc1N0YWJsZSkpLnRvUHJvbWlzZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgY2FjaGVTdGF0ZS5pc0NhY2hlQWN0aXZlID0gZmFsc2U7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICBdO1xufVxuIl19