Skip to content

[Bug]: Incorrect behavior of '?' in the url glob pattern #34915

@vitalets

Description

@vitalets

Version

1.50.1

Steps to reproduce

Per documentation, ? in the url glob pattern matches any character except /. But the following code does not work as expected:

await page.goto('https://playwright.dev');
// notice '?' in the url pattern
await page.route('https://playwright.?ev', async route => {
  console.log('captured!');
  await route.continue();
});
await page.evaluate(() => fetch('https://playwright.dev'));

Expected behavior

Request to https://playwright.dev will be captured.

Actual behavior

Request to https://playwright.dev is not captured.

Additional context

Outside the hostname, ? also behaves in the confusing way. For example:

await page.goto('https://playwright.dev');
// notice '?' in the url pattern
await page.route('https://jsonplaceholder.typicode.com/comments?postId=1', async route => {
  console.log('captured!');
  await route.continue();
});
await page.evaluate(() => fetch('https://jsonplaceholder.typicode.com/comments?postId=1'));

Here, the request to https://jsonplaceholder.typicode.com/comments?postId=1 is matched. But it occurs because ? serves as any symbol, not as a query params separator.
So any of the following requests are matched:

https://jsonplaceholder.typicode.com/comments-postId=1
https://jsonplaceholder.typicode.com/comments_postId=1
https://jsonplaceholder.typicode.com/commentsXpostId=1

I've recently submitted a documentation pr, that highlights that we should escape ? to distinguish query separator from pattern symbol. But with the above example it does not help:

await page.goto('https://playwright.dev');
// notice '?' in the url pattern
await page.route('https://jsonplaceholder.typicode.com/comments\\?postId=1', async route => {
  console.log('captured!');
  await route.continue();
});
await page.evaluate(() => fetch('https://jsonplaceholder.typicode.com/comments?postId=1'));

Request to https://jsonplaceholder.typicode.com/comments?postId=1 is not captured.
The reason: url pattern is passed through new URL() constructor, that is not aware of special meaning for ?. And given url is transformed as follows:

$ node -p 'new URL("https://jsonplaceholder.typicode.com/comments\\?postId=1").toString()'
https://jsonplaceholder.typicode.com/comments/?postId=1

Although it's a valid url, an extra / after comments breaks the comparison, because in the actual request url there is no such normalization:

final pattern: https://jsonplaceholder.typicode.com/comments/?postId=1
real req url:  https://jsonplaceholder.typicode.com/comments?postId=1

The same thing happens with the original example for this bug:

$ node -p 'new URL("https://playwright.?ev").toString()'
https://playwright./?ev

Environment

System:
    OS: macOS 14.7.2
    CPU: (10) arm64 Apple M1 Pro
    Memory: 52.31 MB / 16.00 GB
  Binaries:
    Node: 20.11.1 - ~/.nvm/versions/node/v20.11.1/bin/node
    Yarn: 1.22.22 - ~/.nvm/versions/node/v20.11.1/bin/yarn
    npm: 10.2.4 - ~/.nvm/versions/node/v20.11.1/bin/npm
    pnpm: 9.15.4 - ~/.nvm/versions/node/v20.11.1/bin/pnpm
  Languages:
    Bash: 3.2.57 - /bin/bash
  npmPackages:
    @playwright/test: ^1.50.1 => 1.50.1

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions