diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/UrlMatcher.java b/playwright/src/main/java/com/microsoft/playwright/impl/UrlMatcher.java index 96869901..1fde5359 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/UrlMatcher.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/UrlMatcher.java @@ -16,15 +16,11 @@ package com.microsoft.playwright.impl; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import com.microsoft.playwright.PlaywrightException; -import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -32,7 +28,7 @@ import static com.microsoft.playwright.impl.Utils.toJsRegexFlags; class UrlMatcher { - private final URL baseURL; + private final String baseURL; public final String glob; public final Pattern pattern; public final Predicate predicate; @@ -54,12 +50,17 @@ static UrlMatcher forOneOf(URL baseUrl, Object object) { } static String resolveUrl(URL baseUrl, String spec) { + return resolveUrl(baseUrl.toString(), spec); + } + + private static String resolveUrl(String baseUrl, String spec) { if (baseUrl == null) { return spec; } try { - return new URL(baseUrl, spec).toString(); - } catch (MalformedURLException e) { + // Join using URI instead of URL since URL doesn't handle ws(s) protocols. + return new URI(baseUrl).resolve(spec).toString(); + } catch (URISyntaxException e) { return spec; } } @@ -77,13 +78,17 @@ static String resolveUrl(URL baseUrl, String spec) { } private UrlMatcher(URL baseURL, String glob, Pattern pattern, Predicate predicate) { - this.baseURL = baseURL; + this.baseURL = baseURL != null ? baseURL.toString() : null; this.glob = glob; this.pattern = pattern; this.predicate = predicate; } boolean test(String value) { + return testImpl(baseURL, pattern, predicate, glob, value); + } + + private static boolean testImpl(String baseURL, Pattern pattern, Predicate predicate, String glob, String value) { if (pattern != null) { return pattern.matcher(value).find(); } @@ -91,7 +96,14 @@ boolean test(String value) { return predicate.test(value); } if (glob != null) { - return Pattern.compile(globToRegex(resolveUrl(baseURL, glob))).matcher(value).find(); + if (!glob.startsWith("*")) { + // Allow http(s) baseURL to match ws(s) urls. + if (baseURL != null && Pattern.compile("^https?://").matcher(baseURL).find() && Pattern.compile("^wss?://").matcher(value).find()) { + baseURL = baseURL.replaceFirst("^http", "ws"); + } + glob = resolveUrl(baseURL, glob); + } + return Pattern.compile(globToRegex(glob)).matcher(value).find(); } return true; } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestRouteWebSocket.java b/playwright/src/test/java/com/microsoft/playwright/TestRouteWebSocket.java index c414ac78..fc42cbc6 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestRouteWebSocket.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestRouteWebSocket.java @@ -317,4 +317,38 @@ public void shouldWorkWithoutServer(Page page) { "close code=3008 reason=oops"), page.evaluate("window.log")); } + + @Test + public void shouldWorkWithBaseURL(Browser browser) throws Exception { + BrowserContext context = browser.newContext(new Browser.NewContextOptions().setBaseURL("http://localhost:" + webSocketServer.getPort())); + Page newPage = context.newPage(); + + newPage.routeWebSocket("/ws", ws -> { + ws.onMessage(message -> { + if (message.text() != null) { + System.out.println("ws handler: message: " + message.text()); + ws.send(message.text()); + } else { + System.out.println("ws handler: message: " + message.binary()); + ws.send(message.binary()); + } + }); + }); + + setupWS(newPage, webSocketServer.getPort(), "blob"); + + newPage.evaluate("async () => {\n" + + " await window.wsOpened;\n" + + " window.ws.send('echo');\n" + + " }"); + + newPage.waitForCondition(() -> { + Boolean result = (Boolean) newPage.evaluate("() => window.log.length >= 2"); + return result; + }); + + assertEquals( + asList("open", "message: data=echo origin=ws://localhost:" + webSocketServer.getPort() + " lastEventId="), + newPage.evaluate("window.log")); + } }