Перейти к основному содержимому

Сеть

Введение

Playwright предоставляет API для мониторинга и модификации сетевого трафика браузера, как HTTP, так и HTTPS. Любые запросы, которые делает страница, включая XHR и fetch запросы, могут быть отслежены, изменены и обработаны.

Мокирование API

Ознакомьтесь с нашим руководством по мокированию API, чтобы узнать больше о том, как

  • мокировать API-запросы и никогда не обращаться к API
  • выполнять API-запрос и изменять ответ
  • использовать HAR-файлы для мокирования сетевых запросов.

HTTP-аутентификация

Выполнение HTTP-аутентификации.

using var context = await Browser.NewContextAsync(new()
{
HttpCredentials = new HttpCredentials
{
Username = "bill",
Password = "pa55w0rd"
},
});
var page = await context.NewPageAsync();
await page.GotoAsync("https://example.com");

HTTP-прокси

Вы можете настроить страницы для загрузки через HTTP(S)-прокси или SOCKSv5. Прокси может быть установлен глобально для всего браузера или для каждого контекста браузера отдельно.

Вы можете дополнительно указать имя пользователя и пароль для HTTP(S)-прокси, а также указать хосты, которые следует обходить Proxy.

Вот пример глобального прокси:

var proxy = new Proxy
{
Server = "http://myproxy.com:3128",
Username = "user",
Password = "pwd"
};
await using var browser = await BrowserType.LaunchAsync(new()
{
Proxy = proxy
});

Также возможно указать его для каждого контекста:

await using var browser = await BrowserType.LaunchAsync();
await using var context = await browser.NewContextAsync(new()
{
Proxy = new Proxy { Server = "http://myproxy.com:3128" },
});

Сетевые события

Вы можете отслеживать все Request и Response:

using Microsoft.Playwright;

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
page.Request += (_, request) => Console.WriteLine(">> " + request.Method + " " + request.Url);
page.Response += (_, response) => Console.WriteLine("<< " + response.Status + " " + response.Url);
await page.GotoAsync("https://example.com");

Или дождаться сетевого ответа после нажатия кнопки с помощью Page.RunAndWaitForResponseAsync():

// Используйте шаблон URL с глобальными символами
var waitForResponseTask = page.WaitForResponseAsync("**/api/fetch_data");
await page.GetByText("Update").ClickAsync();
var response = await waitForResponseTask;

Вариации

Ожидание Response с Page.RunAndWaitForResponseAsync()

// Используйте регулярное выражение
var waitForResponseTask = page.WaitForResponseAsync(new Regex("\\.jpeg$"));
await page.GetByText("Update").ClickAsync();
var response = await waitForResponseTask;

// Используйте предикат, принимающий объект Response
var waitForResponseTask = page.WaitForResponseAsync(r => r.Url.Contains(token));
await page.GetByText("Update").ClickAsync();
var response = await waitForResponseTask;

Обработка запросов

Вы можете мокировать API-эндпоинты, обрабатывая сетевые запросы в вашем скрипте Playwright.

Вариации

Настройте маршрут для всего контекста браузера с помощью BrowserContext.RouteAsync() или страницы с Page.RouteAsync(). Это будет применяться к всплывающим окнам и открытым ссылкам.

await page.RouteAsync("**/api/fetch_data", async route => {
await route.FulfillAsync(new() { Status = 200, Body = testData });
});
await page.GotoAsync("https://example.com");

Изменение запросов

// Удаление заголовка
await page.RouteAsync("**/*", async route => {
var headers = new Dictionary<string, string>(route.Request.Headers.ToDictionary(x => x.Key, x => x.Value));
headers.Remove("X-Secret");
await route.ContinueAsync(new() { Headers = headers });
});

// Продолжение запросов как POST.
await Page.RouteAsync("**/*", async route => await route.ContinueAsync(new() { Method = "POST" }));

Вы можете продолжать запросы с модификациями. Пример выше удаляет HTTP-заголовок из исходящих запросов.

Прерывание запросов

Вы можете прерывать запросы, используя Page.RouteAsync() и Route.AbortAsync().

await page.RouteAsync("**/*.{png,jpg,jpeg}", route => route.AbortAsync());

// Прерывание на основе типа запроса
await page.RouteAsync("**/*", async route => {
if ("image".Equals(route.Request.ResourceType))
await route.AbortAsync();
else
await route.ContinueAsync();
});

Изменение ответов

Чтобы изменить ответ, используйте APIRequestContext для получения оригинального ответа, а затем передайте ответ в Route.FulfillAsync(). Вы можете переопределить отдельные поля в ответе через опции:

await Page.RouteAsync("**/title.html", async route =>
{
// Получение оригинального ответа.
var response = await route.FetchAsync();
// Добавление префикса к заголовку.
var body = await response.TextAsync();
body = body.Replace("<title>", "<title>My prefix:");

var headers = response.Headers;
headers.Add("Content-Type", "text/html");

await route.FulfillAsync(new()
{
// Передача всех полей из ответа.
Response = response,
// Переопределение тела ответа.
Body = body,
// Принудительное указание типа контента как html.
Headers = headers,
});
});

Шаблоны URL с глобальными символами

Playwright использует упрощенные шаблоны с глобальными символами для сопоставления URL в методах перехвата сети, таких как Page.RouteAsync() или Page.RunAndWaitForResponseAsync(). Эти шаблоны поддерживают основные подстановочные знаки:

  1. Звездочки:
    • Одиночная * соответствует любым символам, кроме /
    • Двойная ** соответствует любым символам, включая /
  2. Вопросительный знак ? соответствует любому одиночному символу, кроме /
  3. Фигурные скобки {} могут использоваться для сопоставления списка опций, разделенных запятыми ,
  4. Квадратные скобки [] могут использоваться для сопоставления набора символов
  5. Обратная косая черта \ может использоваться для экранирования любых специальных символов (обратите внимание, что для экранирования самой обратной косой черты используйте \\)

Примеры:

  • https://example.com/*.js соответствует https://example.com/file.js, но не https://example.com/path/file.js
  • https://example.com/\\?page=1 соответствует https://example.com/?page=1, но не https://example.com
  • **/v[0-9]* соответствует https://example.com/v1/, но не https://example.com/vote/
  • **/*.js соответствует как https://example.com/file.js, так и https://example.com/path/file.js
  • **/*.{png,jpg,jpeg} соответствует всем запросам изображений

Важные замечания:

  • Шаблон с глобальными символами должен соответствовать всему URL, а не только его части.
  • При использовании шаблонов с глобальными символами для сопоставления URL учитывайте полную структуру URL, включая протокол и разделители пути.
  • Для более сложных требований к сопоставлению рассмотрите возможность использования [RegExp] вместо шаблонов с глобальными символами.

WebSockets

Playwright поддерживает инспекцию, мокирование и модификацию WebSockets из коробки. Ознакомьтесь с нашим руководством по мокированию API, чтобы узнать, как мокировать WebSockets.

Каждый раз, когда создается WebSocket, срабатывает событие Page.WebSocket. Это событие содержит экземпляр WebSocket для дальнейшей инспекции фреймов веб-сокета:

page.WebSocket += (_, ws) =>
{
Console.WriteLine("WebSocket открыт: " + ws.Url);
ws.FrameSent += (_, f) => Console.WriteLine(f.Text);
ws.FrameReceived += (_, f) => Console.WriteLine(f.Text);
ws.Close += (_, ws1) => Console.WriteLine("WebSocket закрыт");
};

Отсутствующие сетевые события и Service Workers

Встроенные BrowserContext.RouteAsync() и Page.RouteAsync() Playwright позволяют вашим тестам нативно маршрутизировать запросы и выполнять мокирование и перехват.

  1. Если вы используете нативные BrowserContext.RouteAsync() и Page.RouteAsync() Playwright, и кажется, что сетевые события отсутствуют, отключите Service Workers, установив ServiceWorkers в 'block'.
  2. Возможно, вы используете инструмент мокирования, такой как Mock Service Worker (MSW). Хотя этот инструмент работает из коробки для мокирования ответов, он добавляет свой собственный Service Worker, который перехватывает сетевые запросы, делая их невидимыми для BrowserContext.RouteAsync() и Page.RouteAsync(). Если вас интересует как тестирование сети, так и мокирование, рассмотрите возможность использования встроенных BrowserContext.RouteAsync() и Page.RouteAsync() для мокирования ответов.
  3. Если вас интересует не только использование Service Workers для тестирования и мокирования сети, но и маршрутизация и прослушивание запросов, сделанных самими Service Workers, пожалуйста, ознакомьтесь с этой экспериментальной функцией.