Skip to content

Commit

Permalink
fix(webSocketRoute): support no trailing slash (#3087)
Browse files Browse the repository at this point in the history
  • Loading branch information
mxschmitt authored Dec 13, 2024
1 parent 9c3d53f commit 0586b06
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 17 deletions.
35 changes: 35 additions & 0 deletions src/Playwright.Tests/PageRouteWebSocketTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,4 +311,39 @@ await AssertAreEqualWithRetriesAsync(() => page.EvaluateAsync<string[]>("() => w
$"message: data=echo origin=ws://localhost:{Server.Port} lastEventId=",
});
}

[PlaywrightTest("page-route-web-socket.spec.ts", "should work with no trailing slash")]
public async Task ShouldWorkWithNoTrailingSlash()
{
var log = new List<string>();
// No trailing slash!
await Page.RouteWebSocketAsync($"ws://localhost:{Server.Port}", ws =>
{
ws.OnMessage(message =>
{
log.Add(message.Text);
ws.Send("response");
});
});

await Page.GotoAsync("about:blank");
await Page.EvaluateAsync(@"({ port }) => {
window.log = [];
// No trailing slash in WebSocket URL
window.ws = new WebSocket('ws://localhost:' + port);
window.ws.addEventListener('message', event => window.log.push(event.data));
}", new Dictionary<string, object>
{
["port"] = Server.Port
});

await Page.WaitForFunctionAsync("() => window.ws.readyState === 1");
await Page.EvaluateAsync("() => window.ws.send('query')");
await AssertAreEqualWithRetriesAsync(
() => Task.FromResult(log.ToArray()),
["query"]);
await AssertAreEqualWithRetriesAsync(
() => Page.EvaluateAsync<string[]>("() => window.log"),
["response"]);
}
}
2 changes: 1 addition & 1 deletion src/Playwright/Core/PageAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public Task ToHaveTitleAsync(Regex titleOrRegExp, PageAssertionsToHaveTitleOptio
ExpectImplAsync("to.have.title", ExpectedRegex(titleOrRegExp, new() { NormalizeWhiteSpace = true }), titleOrRegExp, "Page title expected to be", ConvertToFrameExpectOptions(options));

public Task ToHaveURLAsync(string urlOrRegExp, PageAssertionsToHaveURLOptions options = null) =>
ExpectImplAsync("to.have.url", new ExpectedTextValue() { String = URLMatch.JoinWithBaseURL(_page.Context.Options.BaseURL, urlOrRegExp), IgnoreCase = options?.IgnoreCase }, urlOrRegExp, "Page URL expected to be", ConvertToFrameExpectOptions(options));
ExpectImplAsync("to.have.url", new ExpectedTextValue() { String = URLMatch.ConstructURLBasedOnBaseURL(_page.Context.Options.BaseURL, urlOrRegExp), IgnoreCase = options?.IgnoreCase }, urlOrRegExp, "Page URL expected to be", ConvertToFrameExpectOptions(options));

public Task ToHaveURLAsync(Regex urlOrRegExp, PageAssertionsToHaveURLOptions options = null) =>
ExpectImplAsync("to.have.url", ExpectedRegex(urlOrRegExp, new() { IgnoreCase = options?.IgnoreCase }), urlOrRegExp, "Page URL expected to match regex", ConvertToFrameExpectOptions(options));
Expand Down
42 changes: 26 additions & 16 deletions src/Playwright/Helpers/URLMatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public class URLMatch
public string baseURL { get; set; }

public bool Match(string url)
{
return MatchImpl(url, re, func, glob, baseURL);
}

private static bool MatchImpl(string url, Regex re, Func<string, bool> func, string glob, string baseURL)
{
if (re != null)
{
Expand All @@ -51,33 +56,38 @@ public bool Match(string url)

if (glob != null)
{
var globWithBaseURL = JoinWithBaseURL(baseURL, glob);
// Allow http(s) baseURL to match ws(s) urls.
if (new Regex("^https?://").IsMatch(globWithBaseURL) && new Regex("^wss?://").IsMatch(url))
if (string.IsNullOrEmpty(glob))
{
globWithBaseURL = new Regex("^http").Replace(globWithBaseURL, "ws");
return true;
}
return new Regex(globWithBaseURL.GlobToRegex()).IsMatch(url);
if (!glob.StartsWith("*", StringComparison.InvariantCultureIgnoreCase))
{
// Allow http(s) baseURL to match ws(s) urls.
if (!string.IsNullOrEmpty(baseURL) && new Regex("^https?://").IsMatch(baseURL) && new Regex("^wss?://").IsMatch(url))
{
baseURL = new Regex("^http").Replace(baseURL, "ws");
}
glob = ConstructURLBasedOnBaseURL(baseURL, glob);
}
return new Regex(glob.GlobToRegex()).IsMatch(url);
}
return true;
}

internal static string JoinWithBaseURL(string baseUrl, string url)
internal static string ConstructURLBasedOnBaseURL(string baseUrl, string url)
{
if (string.IsNullOrEmpty(baseUrl)
|| (url?.StartsWith("*", StringComparison.InvariantCultureIgnoreCase) ?? false)
|| !Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
try
{
return url;
if (string.IsNullOrEmpty(baseUrl))
{
return new Uri(url, UriKind.Absolute).ToString();
}
return new Uri(new Uri(baseUrl), new Uri(url, UriKind.RelativeOrAbsolute)).ToString();
}

var mUri = new Uri(url, UriKind.RelativeOrAbsolute);
if (!mUri.IsAbsoluteUri)
catch
{
return new Uri(new Uri(baseUrl), mUri).ToString();
return url;
}

return url;
}

public bool Equals(string globMatch, Regex reMatch, Func<string, bool> funcMatch, string baseURL)
Expand Down

0 comments on commit 0586b06

Please sign in to comment.