From 9e8b3eab7ff5770b2551e98819370623d3726a78 Mon Sep 17 00:00:00 2001 From: Joel Griffith Date: Fri, 17 Jan 2020 16:43:12 -0800 Subject: [PATCH] [7.x] [Reporting] Fix map tiles not loading by using Chrome's Remote Protocol (#55137) (#55235) * [Reporting] Fix map tiles not loading by using Chrome's Remote Protocol (#55137) * WIP Fixing map tiles and such * Small comment and importing map from dolash * Better destructuring and comments Co-authored-by: Elastic Machine * Fixing type woes in reportin' * Fixing dupe export Co-authored-by: Elastic Machine --- .../chromium/driver/chromium_driver.ts | 41 +++++++++++++++---- x-pack/legacy/plugins/reporting/types.d.ts | 15 +++++++ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts index c1777038cc7d4..de8449ff29132 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { trunc } from 'lodash'; +import { trunc, map } from 'lodash'; import open from 'opn'; import { parse as parseUrl } from 'url'; import { Page, SerializableOrJSHandle, EvaluateFn } from 'puppeteer'; @@ -15,6 +15,7 @@ import { ConditionalHeaders, ConditionalHeadersConditions, ElementPosition, + InterceptedRequest, NetworkPolicy, } from '../../../../types'; @@ -59,35 +60,57 @@ export class HeadlessChromiumDriver { }: { conditionalHeaders: ConditionalHeaders; waitForSelector: string }, logger: LevelLogger ) { - await this.page.setRequestInterception(true); logger.info(`opening url ${url}`); + // @ts-ignore + const client = this.page._client; let interceptedCount = 0; - this.page.on('request', interceptedRequest => { - const interceptedUrl = interceptedRequest.url(); + await this.page.setRequestInterception(true); + + // We have to reach into the Chrome Devtools Protocol to apply headers as using + // puppeteer's API will cause map tile requests to hang indefinitely: + // https://github.com/puppeteer/puppeteer/issues/5003 + // Docs on this client/protocol can be found here: + // https://chromedevtools.github.io/devtools-protocol/tot/Fetch + client.on('Fetch.requestPaused', (interceptedRequest: InterceptedRequest) => { + const { + requestId, + request: { url: interceptedUrl }, + } = interceptedRequest; const allowed = !interceptedUrl.startsWith('file://'); const isData = interceptedUrl.startsWith('data:'); // We should never ever let file protocol requests go through if (!allowed || !this.allowRequest(interceptedUrl)) { logger.error(`Got bad URL: "${interceptedUrl}", closing browser.`); - interceptedRequest.abort('blockedbyclient'); + client.send('Fetch.failRequest', { + errorReason: 'Aborted', + requestId, + }); this.page.browser().close(); throw new Error(`Received disallowed outgoing URL: "${interceptedUrl}", exiting`); } if (this._shouldUseCustomHeaders(conditionalHeaders.conditions, interceptedUrl)) { logger.debug(`Using custom headers for ${interceptedUrl}`); - interceptedRequest.continue({ - headers: { - ...interceptedRequest.headers(), + const headers = map( + { + ...interceptedRequest.request.headers, ...conditionalHeaders.headers, }, + (value, name) => ({ + name, + value, + }) + ); + client.send('Fetch.continueRequest', { + requestId, + headers, }); } else { const loggedUrl = isData ? this.truncateUrl(interceptedUrl) : interceptedUrl; logger.debug(`No custom headers for ${loggedUrl}`); - interceptedRequest.continue(); + client.send('Fetch.continueRequest', { requestId }); } interceptedCount = interceptedCount + (isData ? 0 : 1); }); diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index e7c953671fce1..a9df4171b2591 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -340,3 +340,18 @@ export interface AbsoluteURLFactoryOptions { hostname: string; port: string | number; } + +export interface InterceptedRequest { + requestId: string; + request: { + url: string; + method: string; + headers: { + [key: string]: string; + }; + initialPriority: string; + referrerPolicy: string; + }; + frameId: string; + resourceType: string; +}