mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: resolve glob to regex in local utils for language ports (#35136)
This commit is contained in:
parent
85a66912c6
commit
74acbcea56
@ -603,7 +603,7 @@ export class WebSocketRouteHandler {
|
||||
}
|
||||
|
||||
public matches(wsURL: string): boolean {
|
||||
return urlMatches(this._baseURL, wsURL, this.url);
|
||||
return urlMatches(this._baseURL, wsURL, this.url, true);
|
||||
}
|
||||
|
||||
public async handle(webSocketRoute: WebSocketRoute) {
|
||||
|
||||
@ -344,6 +344,14 @@ scheme.LocalUtilsTraceDiscardedParams = tObject({
|
||||
stacksId: tString,
|
||||
});
|
||||
scheme.LocalUtilsTraceDiscardedResult = tOptional(tObject({}));
|
||||
scheme.LocalUtilsGlobToRegexParams = tObject({
|
||||
glob: tString,
|
||||
baseURL: tOptional(tString),
|
||||
webSocketUrl: tOptional(tBoolean),
|
||||
});
|
||||
scheme.LocalUtilsGlobToRegexResult = tObject({
|
||||
regex: tString,
|
||||
});
|
||||
scheme.RootInitializer = tOptional(tObject({}));
|
||||
scheme.RootInitializeParams = tObject({
|
||||
sdkLanguage: tEnum(['javascript', 'python', 'java', 'csharp']),
|
||||
|
||||
@ -24,6 +24,7 @@ import { Progress, ProgressController } from '../progress';
|
||||
import { SocksInterceptor } from '../socksInterceptor';
|
||||
import { WebSocketTransport } from '../transport';
|
||||
import { fetchData } from '../utils/network';
|
||||
import { resolveGlobToRegexPattern } from '../../utils/isomorphic/urlMatch';
|
||||
|
||||
import type { HarBackend } from '../harBackend';
|
||||
import type { CallMetadata } from '../instrumentation';
|
||||
@ -120,6 +121,11 @@ export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels.
|
||||
return { pipe, headers: transport.headers };
|
||||
}, params.timeout || 0);
|
||||
}
|
||||
|
||||
async globToRegex(params: channels.LocalUtilsGlobToRegexParams, metadata?: CallMetadata): Promise<channels.LocalUtilsGlobToRegexResult> {
|
||||
const regex = resolveGlobToRegexPattern(params.baseURL, params.glob, params.webSocketUrl);
|
||||
return { regex };
|
||||
}
|
||||
}
|
||||
|
||||
async function urlToWSEndpoint(progress: Progress | undefined, endpointURL: string): Promise<string> {
|
||||
|
||||
@ -148,7 +148,7 @@ export class WebSocketRouteDispatcher extends Dispatcher<{ guid: string }, chann
|
||||
function matchesPattern(dispatcher: PageDispatcher | BrowserContextDispatcher, baseURL: string | undefined, url: string) {
|
||||
for (const pattern of dispatcher._webSocketInterceptionPatterns || []) {
|
||||
const urlMatch = pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags) : pattern.glob;
|
||||
if (urlMatches(baseURL, url, urlMatch))
|
||||
if (urlMatches(baseURL, url, urlMatch, true))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -19,7 +19,7 @@ import { isString } from './stringUtils';
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping
|
||||
const escapedChars = new Set(['$', '^', '+', '.', '*', '(', ')', '|', '\\', '?', '{', '}', '[', ']']);
|
||||
|
||||
export function globToRegex(glob: string): RegExp {
|
||||
export function globToRegexPattern(glob: string): string {
|
||||
const tokens = ['^'];
|
||||
let inGroup = false;
|
||||
for (let i = 0; i < glob.length; ++i) {
|
||||
@ -70,7 +70,7 @@ export function globToRegex(glob: string): RegExp {
|
||||
}
|
||||
}
|
||||
tokens.push('$');
|
||||
return new RegExp(tokens.join(''));
|
||||
return tokens.join('');
|
||||
}
|
||||
|
||||
function isRegExp(obj: any): obj is RegExp {
|
||||
@ -85,14 +85,39 @@ export function urlMatchesEqual(match1: URLMatch, match2: URLMatch) {
|
||||
return match1 === match2;
|
||||
}
|
||||
|
||||
export function urlMatches(baseURL: string | undefined, urlString: string, match: URLMatch | undefined): boolean {
|
||||
export function urlMatches(baseURL: string | undefined, urlString: string, match: URLMatch | undefined, webSocketUrl?: boolean): boolean {
|
||||
if (match === undefined || match === '')
|
||||
return true;
|
||||
if (isString(match) && !match.startsWith('*')) {
|
||||
// Allow http(s) baseURL to match ws(s) urls.
|
||||
if (baseURL && /^https?:\/\//.test(baseURL) && /^wss?:\/\//.test(urlString))
|
||||
baseURL = baseURL.replace(/^http/, 'ws');
|
||||
if (isString(match))
|
||||
match = new RegExp(resolveGlobToRegexPattern(baseURL, match, webSocketUrl));
|
||||
if (isRegExp(match)) {
|
||||
const r = match.test(urlString);
|
||||
return r;
|
||||
}
|
||||
const url = parseURL(urlString);
|
||||
if (!url)
|
||||
return false;
|
||||
if (typeof match !== 'function')
|
||||
throw new Error('url parameter should be string, RegExp or function');
|
||||
return match(url);
|
||||
}
|
||||
|
||||
export function resolveGlobToRegexPattern(baseURL: string | undefined, glob: string, webSocketUrl?: boolean): string {
|
||||
if (webSocketUrl)
|
||||
baseURL = toWebSocketBaseUrl(baseURL);
|
||||
glob = resolveGlobBase(baseURL, glob);
|
||||
return globToRegexPattern(glob);
|
||||
}
|
||||
|
||||
function toWebSocketBaseUrl(baseURL: string | undefined) {
|
||||
// Allow http(s) baseURL to match ws(s) urls.
|
||||
if (baseURL && /^https?:\/\//.test(baseURL))
|
||||
baseURL = baseURL.replace(/^http/, 'ws');
|
||||
return baseURL;
|
||||
}
|
||||
|
||||
function resolveGlobBase(baseURL: string | undefined, match: string): string {
|
||||
if (!match.startsWith('*')) {
|
||||
const tokenMap = new Map<string, string>();
|
||||
function mapToken(original: string, replacement: string) {
|
||||
if (original.length === 0)
|
||||
@ -123,16 +148,7 @@ export function urlMatches(baseURL: string | undefined, urlString: string, match
|
||||
resolved = resolved.replace(token, original);
|
||||
match = resolved;
|
||||
}
|
||||
if (isString(match))
|
||||
match = globToRegex(match);
|
||||
if (isRegExp(match))
|
||||
return match.test(urlString);
|
||||
const url = parseURL(urlString);
|
||||
if (!url)
|
||||
return false;
|
||||
if (typeof match !== 'function')
|
||||
throw new Error('url parameter should be string, RegExp or function');
|
||||
return match(url);
|
||||
return match;
|
||||
}
|
||||
|
||||
function parseURL(url: string): URL | null {
|
||||
|
||||
13
packages/protocol/src/channels.d.ts
vendored
13
packages/protocol/src/channels.d.ts
vendored
@ -473,6 +473,7 @@ export interface LocalUtilsChannel extends LocalUtilsEventTarget, Channel {
|
||||
tracingStarted(params: LocalUtilsTracingStartedParams, metadata?: CallMetadata): Promise<LocalUtilsTracingStartedResult>;
|
||||
addStackToTracingNoReply(params: LocalUtilsAddStackToTracingNoReplyParams, metadata?: CallMetadata): Promise<LocalUtilsAddStackToTracingNoReplyResult>;
|
||||
traceDiscarded(params: LocalUtilsTraceDiscardedParams, metadata?: CallMetadata): Promise<LocalUtilsTraceDiscardedResult>;
|
||||
globToRegex(params: LocalUtilsGlobToRegexParams, metadata?: CallMetadata): Promise<LocalUtilsGlobToRegexResult>;
|
||||
}
|
||||
export type LocalUtilsZipParams = {
|
||||
zipFile: string,
|
||||
@ -572,6 +573,18 @@ export type LocalUtilsTraceDiscardedOptions = {
|
||||
|
||||
};
|
||||
export type LocalUtilsTraceDiscardedResult = void;
|
||||
export type LocalUtilsGlobToRegexParams = {
|
||||
glob: string,
|
||||
baseURL?: string,
|
||||
webSocketUrl?: boolean,
|
||||
};
|
||||
export type LocalUtilsGlobToRegexOptions = {
|
||||
baseURL?: string,
|
||||
webSocketUrl?: boolean,
|
||||
};
|
||||
export type LocalUtilsGlobToRegexResult = {
|
||||
regex: string,
|
||||
};
|
||||
|
||||
export interface LocalUtilsEvents {
|
||||
}
|
||||
|
||||
@ -705,6 +705,14 @@ LocalUtils:
|
||||
parameters:
|
||||
stacksId: string
|
||||
|
||||
globToRegex:
|
||||
parameters:
|
||||
glob: string
|
||||
baseURL: string?
|
||||
webSocketUrl: boolean?
|
||||
returns:
|
||||
regex: string
|
||||
|
||||
Root:
|
||||
type: interface
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { test as it, expect } from './pageTest';
|
||||
import { globToRegex, urlMatches } from '../../packages/playwright-core/lib/utils/isomorphic/urlMatch';
|
||||
import { globToRegexPattern, urlMatches } from '../../packages/playwright-core/lib/utils/isomorphic/urlMatch';
|
||||
import vm from 'vm';
|
||||
|
||||
it('should work with navigation @smoke', async ({ page, server }) => {
|
||||
@ -71,6 +71,9 @@ it('should intercept after a service worker', async ({ page, server, browserName
|
||||
});
|
||||
|
||||
it('should work with glob', async () => {
|
||||
function globToRegex(glob: string): RegExp {
|
||||
return new RegExp(globToRegexPattern(glob));
|
||||
}
|
||||
expect(globToRegex('**/*.js').test('https://localhost:8080/foo.js')).toBeTruthy();
|
||||
expect(globToRegex('**/*.css').test('https://localhost:8080/foo.js')).toBeFalsy();
|
||||
expect(globToRegex('*.js').test('https://localhost:8080/foo.js')).toBeFalsy();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user