Skip to content

Commit

Permalink
fix(route): handle escapes in the glob pattern (#23932)
Browse files Browse the repository at this point in the history
Fixes #23303.
  • Loading branch information
dgozman authored Jun 28, 2023
1 parent 1ab99fe commit 1d0b48f
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 5 deletions.
12 changes: 7 additions & 5 deletions packages/playwright-core/src/utils/glob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@
* limitations under the License.
*/

const escapeGlobChars = new Set(['/', '$', '^', '+', '.', '(', ')', '=', '!', '|']);
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#escaping
const escapedChars = new Set(['$', '^', '+', '.', '*', '(', ')', '|', '\\', '?', '{', '}', '[', ']']);

export function globToRegex(glob: string): RegExp {
const tokens = ['^'];
let inGroup;
let inGroup = false;
for (let i = 0; i < glob.length; ++i) {
const c = glob[i];
if (escapeGlobChars.has(c)) {
tokens.push('\\' + c);
if (c === '\\' && i + 1 < glob.length) {
const char = glob[++i];
tokens.push(escapedChars.has(char) ? '\\' + char : char);
continue;
}
if (c === '*') {
Expand Down Expand Up @@ -65,7 +67,7 @@ export function globToRegex(glob: string): RegExp {
tokens.push('\\' + c);
break;
default:
tokens.push(c);
tokens.push(escapedChars.has(c) ? '\\' + c : c);
}
}
tokens.push('$');
Expand Down
7 changes: 7 additions & 0 deletions tests/page/interception.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ it('should work with glob', async () => {
expect(globToRegex('foo*').test('foo/bar.js')).toBeFalsy();
expect(globToRegex('http://localhost:3000/signin-oidc*').test('http://localhost:3000/signin-oidc/foo')).toBeFalsy();
expect(globToRegex('http://localhost:3000/signin-oidc*').test('http://localhost:3000/signin-oidcnice')).toBeTruthy();

expect(globToRegex('\\?')).toEqual(/^\?$/);
expect(globToRegex('\\')).toEqual(/^\\$/);
expect(globToRegex('\\\\')).toEqual(/^\\$/);
expect(globToRegex('\\[')).toEqual(/^\[$/);
expect(globToRegex('[')).toEqual(/^\[$/);
expect(globToRegex('$^+.\\*()|\\?\\{\\}[]')).toEqual(/^\$\^\+\.\*\(\)\|\?\{\}\[\]$/);
});

it('should intercept network activity from worker', async function({ page, server, isAndroid, browserName, browserMajorVersion }) {
Expand Down
26 changes: 26 additions & 0 deletions tests/page/page-route.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,32 @@ it('should unroute', async ({ page, server }) => {
expect(intercepted).toEqual([1]);
});

it('should support ? in glob pattern', async ({ page, server }) => {
server.setRoute('/index', (req, res) => res.end('index-no-hello'));
server.setRoute('/index123hello', (req, res) => res.end('index123hello'));
server.setRoute('/index?hello', (req, res) => res.end('index?hello'));

await page.route('**/index?hello', async (route, request) => {
await route.fulfill({ body: 'intercepted any character' });
});

await page.route('**/index\\?hello', async (route, request) => {
await route.fulfill({ body: 'intercepted question mark' });
});

await page.goto(server.PREFIX + '/index?hello');
expect(await page.content()).toContain('intercepted question mark');

await page.goto(server.PREFIX + '/index');
expect(await page.content()).toContain('index-no-hello');

await page.goto(server.PREFIX + '/index1hello');
expect(await page.content()).toContain('intercepted any character');

await page.goto(server.PREFIX + '/index123hello');
expect(await page.content()).toContain('index123hello');
});

it('should work when POST is redirected with 302', async ({ page, server }) => {
server.setRedirect('/rredirect', '/empty.html');
await page.goto(server.EMPTY_PAGE);
Expand Down

0 comments on commit 1d0b48f

Please sign in to comment.