chore: remove route/unroute from the server side (#3518)

We only use a global "intercept all requests" handler on
page and browser context, instead of granular ones.
This commit is contained in:
Dmitry Gozman 2020-08-18 17:34:04 -07:00 committed by GitHub
parent 3cf48f9bd4
commit 20c6b85178
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 27 additions and 67 deletions

View file

@ -44,8 +44,7 @@ export interface BrowserContext extends EventEmitter {
setHTTPCredentials(httpCredentials?: types.Credentials): Promise<void>;
addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any): Promise<void>;
exposeBinding(name: string, playwrightBinding: frames.FunctionWithSource): Promise<void>;
route(url: types.URLMatch, handler: network.RouteHandler): Promise<void>;
unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void>;
_setRequestInterceptor(handler: network.RouteHandler | undefined): Promise<void>;
close(): Promise<void>;
}
@ -53,7 +52,7 @@ export abstract class BrowserContextBase extends EventEmitter implements Browser
readonly _timeoutSettings = new TimeoutSettings();
readonly _pageBindings = new Map<string, PageBinding>();
readonly _options: types.BrowserContextOptions;
_routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
_requestInterceptor?: network.RouteHandler;
private _isPersistentContext: boolean;
private _closedStatus: 'open' | 'closing' | 'closed' = 'open';
readonly _closePromise: Promise<Error>;
@ -107,8 +106,7 @@ export abstract class BrowserContextBase extends EventEmitter implements Browser
abstract setOffline(offline: boolean): Promise<void>;
abstract _doAddInitScript(expression: string): Promise<void>;
abstract _doExposeBinding(binding: PageBinding): Promise<void>;
abstract route(url: types.URLMatch, handler: network.RouteHandler): Promise<void>;
abstract unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void>;
abstract _doUpdateRequestInterception(): Promise<void>;
abstract _doClose(): Promise<void>;
async cookies(urls: string | string[] | undefined = []): Promise<types.NetworkCookie[]> {
@ -206,6 +204,11 @@ export abstract class BrowserContextBase extends EventEmitter implements Browser
this._options.httpCredentials = { username, password };
}
async _setRequestInterceptor(handler: network.RouteHandler | undefined): Promise<void> {
this._requestInterceptor = handler;
await this._doUpdateRequestInterception();
}
async close() {
if (this._isPersistentContext) {
// Default context is only created in 'persistent' mode and closing it should close

View file

@ -416,14 +416,7 @@ export class CRBrowserContext extends BrowserContextBase {
await (page._delegate as CRPage).exposeBinding(binding);
}
async route(url: types.URLMatch, handler: network.RouteHandler): Promise<void> {
this._routes.push({ url, handler });
for (const page of this.pages())
await (page._delegate as CRPage).updateRequestInterception();
}
async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
async _doUpdateRequestInterception(): Promise<void> {
for (const page of this.pages())
await (page._delegate as CRPage).updateRequestInterception();
}

View file

@ -191,7 +191,7 @@ export class CRNetworkManager {
if (requestPausedEvent) {
// CORS options request is generated by the network stack, it is not associated with the frame id.
// If URL matches interception pattern, accept it, assuming that this was intended when setting route.
if (requestPausedEvent.request.method === 'OPTIONS' && this._page._isRouted(requestPausedEvent.request.url)) {
if (requestPausedEvent.request.method === 'OPTIONS' && this._page._needsRequestInterception()) {
const requestHeaders = requestPausedEvent.request.headers;
const responseHeaders: Protocol.Fetch.HeaderEntry[] = [
{ name: 'Access-Control-Allow-Origin', value: requestHeaders['Origin'] || '*' },

View file

@ -319,16 +319,8 @@ export class FFBrowserContext extends BrowserContextBase {
await this._browser._connection.send('Browser.addBinding', { browserContextId: this._browserContextId || undefined, name: binding.name, script: binding.source });
}
async route(url: types.URLMatch, handler: network.RouteHandler): Promise<void> {
this._routes.push({ url, handler });
if (this._routes.length === 1)
await this._browser._connection.send('Browser.setRequestInterception', { browserContextId: this._browserContextId || undefined, enabled: true });
}
async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
if (this._routes.length === 0)
await this._browser._connection.send('Browser.setRequestInterception', { browserContextId: this._browserContextId || undefined, enabled: false });
async _doUpdateRequestInterception(): Promise<void> {
await this._browser._connection.send('Browser.setRequestInterception', { browserContextId: this._browserContextId || undefined, enabled: !!this._requestInterceptor });
}
async _doClose() {

View file

@ -113,7 +113,7 @@ export class Page extends EventEmitter {
private _workers = new Map<string, Worker>();
readonly pdf: ((options?: types.PDFOptions) => Promise<Buffer>) | undefined;
readonly coverage: any;
_routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
private _requestInterceptor?: network.RouteHandler;
_ownedContext: BrowserContext | undefined;
constructor(delegate: PageDelegate, browserContext: BrowserContextBase) {
@ -291,16 +291,11 @@ export class Page extends EventEmitter {
}
_needsRequestInterception(): boolean {
return this._routes.length > 0 || this._browserContext._routes.length > 0;
return !!this._requestInterceptor || !!this._browserContext._requestInterceptor;
}
async route(url: types.URLMatch, handler: network.RouteHandler): Promise<void> {
this._routes.push({ url, handler });
await this._delegate.updateRequestInterception();
}
async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
async _setRequestInterceptor(handler: network.RouteHandler | undefined): Promise<void> {
this._requestInterceptor = handler;
await this._delegate.updateRequestInterception();
}
@ -309,33 +304,17 @@ export class Page extends EventEmitter {
const route = request._route();
if (!route)
return;
for (const { url, handler } of this._routes) {
if (helper.urlMatches(request.url(), url)) {
handler(route, request);
return;
}
if (this._requestInterceptor) {
this._requestInterceptor(route, request);
return;
}
for (const { url, handler } of this._browserContext._routes) {
if (helper.urlMatches(request.url(), url)) {
handler(route, request);
return;
}
if (this._browserContext._requestInterceptor) {
this._browserContext._requestInterceptor(route, request);
return;
}
route.continue();
}
_isRouted(requestURL: string): boolean {
for (const { url } of this._routes) {
if (helper.urlMatches(requestURL, url))
return true;
}
for (const { url } of this._browserContext._routes) {
if (helper.urlMatches(requestURL, url))
return true;
}
return false;
}
async screenshot(options: types.ScreenshotOptions = {}): Promise<Buffer> {
return this._runAbortableTask(
progress => this._screenshotter.screenshotPage(progress, options),

View file

@ -112,10 +112,10 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, Browser
async setNetworkInterceptionEnabled(params: { enabled: boolean }): Promise<void> {
if (!params.enabled) {
await this._context.unroute('**/*');
await this._context._setRequestInterceptor(undefined);
return;
}
this._context.route('**/*', (route, request) => {
this._context._setRequestInterceptor((route, request) => {
this._dispatchEvent('route', { route: new RouteDispatcher(this._scope, route), request: RequestDispatcher.from(this._scope, request) });
});
}

View file

@ -123,10 +123,10 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
async setNetworkInterceptionEnabled(params: { enabled: boolean }): Promise<void> {
if (!params.enabled) {
await this._page.unroute('**/*');
await this._page._setRequestInterceptor(undefined);
return;
}
this._page.route('**/*', (route, request) => {
this._page._setRequestInterceptor((route, request) => {
this._dispatchEvent('route', { route: new RouteDispatcher(this._scope, route), request: RequestDispatcher.from(this._scope, request) });
});
}

View file

@ -322,14 +322,7 @@ export class WKBrowserContext extends BrowserContextBase {
await (page._delegate as WKPage).exposeBinding(binding);
}
async route(url: types.URLMatch, handler: network.RouteHandler): Promise<void> {
this._routes.push({ url, handler });
for (const page of this.pages())
await (page._delegate as WKPage).updateRequestInterception();
}
async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
async _doUpdateRequestInterception(): Promise<void> {
for (const page of this.pages())
await (page._delegate as WKPage).updateRequestInterception();
}