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

Сеть

Введение

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

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

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

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

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

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

BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setHttpCredentials("bill", "pa55w0rd"));
Page page = context.newPage();
page.navigate("https://example.com");

HTTP-прокси

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

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

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

Browser browser = chromium.launch(new BrowserType.LaunchOptions()
.setProxy(new Proxy("http://myproxy.com:3128")
.setUsername("usr")
.setPassword("pwd")));

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

Browser browser = chromium.launch();
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setProxy(new Proxy("http://myproxy.com:3128")));

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

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

import com.microsoft.playwright.*;

public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType chromium = playwright.chromium();
Browser browser = chromium.launch();
Page page = browser.newPage();
page.onRequest(request -> System.out.println(">> " + request.method() + " " + request.url()));
page.onResponse(response -> System.out.println("<<" + response.status() + " " + response.url()));
page.navigate("https://example.com");
browser.close();
}
}
}

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

// Используйте шаблон URL с глобом
Response response = page.waitForResponse("**/api/fetch_data", () -> {
page.getByText("Update").click();
});

Вариации

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

// Используйте RegExp
Response response = page.waitForResponse(Pattern.compile("\\.jpeg$"), () -> {
page.getByText("Update").click();
});

// Используйте предикат, принимающий объект Response
Response response = page.waitForResponse(r -> r.url().contains(token), () -> {
page.getByText("Update").click();
});

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

page.route("**/api/fetch_data", route -> route.fulfill(new Route.FulfillOptions()
.setStatus(200)
.setBody(testData)));
page.navigate("https://example.com");

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

Вариации

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

browserContext.route("**/api/login", route -> route.fulfill(new Route.FulfillOptions()
.setStatus(200)
.setBody("accept")));
page.navigate("https://example.com");

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

// Удаление заголовка
page.route("**/*", route -> {
Map<String, String> headers = new HashMap<>(route.request().headers());
headers.remove("X-Secret");
route.resume(new Route.ResumeOptions().setHeaders(headers));
});

// Продолжение запросов как POST.
page.route("**/*", route -> route.resume(new Route.ResumeOptions().setMethod("POST")));

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

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

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

page.route("**/*.{png,jpg,jpeg}", route -> route.abort());

// Прерывание на основе типа запроса
page.route("**/*", route -> {
if ("image".equals(route.request().resourceType()))
route.abort();
else
route.resume();
});

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

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

page.route("**/title.html", route -> {
// Получение оригинального ответа.
APIResponse response = route.fetch();
// Добавление префикса к заголовку.
String body = response.text();
body = body.replace("<title>", "<title>My prefix:");
Map<String, String> headers = response.headers();
headers.put("content-type", "text/html");
route.fulfill(new Route.FulfillOptions()
// Передача всех полей из ответа.
.setResponse(response)
// Переопределение тела ответа.
.setBody(body)
// Принудительное указание типа контента как html.
.setHeaders(headers));
});

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

Playwright использует упрощённые glob-паттерны для сопоставления URL в методах перехвата сетевых запросов, таких как Page.route() или Page.waitForResponse(). Эти паттерны поддерживают базовые подстановочные символы:

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

Примеры:

  • 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
  • **/*.js соответствует и https://example.com/file.js, и https://example.com/path/file.js
  • **/*.{png,jpg,jpeg} соответствует всем запросам изображений

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

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

Веб-сокеты

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

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

page.onWebSocket(ws -> {
log("WebSocket opened: " + ws.url());
ws.onFrameSent(frameData -> log(frameData.text()));
ws.onFrameReceived(frameData -> log(frameData.text()));
ws.onClose(ws1 -> log("WebSocket closed"));
});

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

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

Если вы используете нативные BrowserContext.route() и Page.route(), и вам кажется, что часть сетевых событий пропадает, отключите Service Workers, установив setServiceWorkers в значение 'block'.

Возможно, вы используете инструмент для мокинга, например Mock Service Worker (MSW). Хотя он «из коробки» подходит для мокинга ответов, он добавляет собственный Service Worker, который перехватывает сетевые запросы, из-за чего они становятся невидимыми для BrowserContext.route() и Page.route(). Если вам важны и сетевое тестирование, и мокинг, рассмотрите использование встроенных BrowserContext.route() и Page.route() для мокинга ответов.