Фильтрация запросов по типу и URL

Появление Puppeteer предоставило разработчикам мощный инструмент для автоматизации тестирования веб-приложений. Одним из самых востребованных аспектов в автоматизированном тестировании является возможность фильтровать запросы, отправляемые браузером, для того чтобы ограничить или изменить поведение страницы. В Puppeteer это достигается с помощью возможности перехватывать сетевые запросы, а затем фильтровать их по определённым критериям, таким как тип ресурса или URL.

Перехват сетевых запросов

Перехват сетевых запросов — это процесс, при котором можно перехватывать запросы, отправляемые браузером, и обрабатывать их до того, как они попадут на сервер. В Puppeteer для этого используется метод page.setRequestInterception(true). Он активирует возможность перехвата запросов на уровне страницы.

const puppeteer = require(&

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.setRequestInterception(true);

  page.on('request', request => {
    console.log('Перехваченный запрос:', request.url());
    request.continue();
  });

  await page.goto('https://example.com');
  await browser.close();
})();

В этом примере с помощью метода page.on(‘request’, …) мы настраиваем обработчик для перехвата всех запросов, отправляемых страницей. Важно заметить, что после перехвата запроса необходимо явно указать, что делать с ним. Метод request.continue() сообщает Puppeteer, что запрос должен быть продолжен, и браузер должен его выполнить.

Фильтрация запросов по типу

После того как перехват запроса включён, можно настроить фильтрацию запросов по их типу. Тип запроса определяется на основе MIME-типа ресурса, который запрашивается. Для фильтрации по типу используется свойство request.resourceType(). Это свойство позволяет определить, какой тип ресурса запрашивается в данный момент.

Типы ресурсов могут включать:

  • document — HTML-документ
  • stylesheet — таблица стилей
  • image — изображение
  • media — видео или аудио
  • font — шрифт
  • script — JavaScript
  • xhr — AJAX-запросы
  • fetch — Fetch API запросы
  • websocket — WebSocket запросы

Пример фильтрации запросов по типу ресурса:

page.on('request', request => {
  const resourceType = request.resourceType();
  
  // Пропускаем все запросы, кроме изображений
  if (resourceType === 'image') {
    request.continue();
  } else {
    request.abort();
  }
});

В данном примере перехватываются все запросы на странице, но выполняются только те из них, которые касаются изображений. Все остальные запросы прерываются с помощью метода request.abort().

Фильтрация запросов по URL

Кроме того, можно фильтровать запросы по URL. Это особенно полезно, когда необходимо блокировать или изменять поведение запросов к определённым адресам. URL может быть проверен на наличие определённых подстрок или полных совпадений.

Пример фильтрации запросов по URL:

page.on('request', request => {
  const url = request.url();
  
  // Пропускаем запросы к домену example.com, остальные блокируем
  if (url.includes('example.com')) {
    request.continue();
  } else {
    request.abort();
  }
});

В данном примере пропускаются только те запросы, которые содержат подстроку example.com в URL. Все остальные запросы блокируются.

Можно использовать регулярные выражения для более гибкой фильтрации:

page.on('request', request => {
  const url = request.url();
  
  // Пропускаем запросы к адресам, начинающимся с https://example.com/api/
  const apiUrlPattern = /^https:\/\/example\.com\/api\//;
  if (apiUrlPattern.test(url)) {
    request.continue();
  } else {
    request.abort();
  }
});

В этом примере запросы, которые начинаются с https://example.com/api/, будут пропущены, а остальные — заблокированы.

Комбинированная фильтрация по типу и URL

Часто возникает необходимость фильтровать запросы по нескольким критериям одновременно. Для этого можно комбинировать фильтрацию по типу ресурса и URL. Например, можно пропускать только те запросы, которые относятся к изображениям и имеют определённый домен в URL.

Пример комбинированной фильтрации:

page.on('request', request => {
  const resourceType = request.resourceType();
  const url = request.url();
  
  // Пропускаем только запросы к изображениям с домена example.com
  if (resourceType === 'image' && url.includes('example.com')) {
    request.continue();
  } else {
    request.abort();
  }
});

Здесь пропускаются только запросы на изображения, если их URL содержит example.com. Все другие запросы блокируются.

Обработка сетевых ответов

После перехвата запросов может возникнуть необходимость обработки ответов, приходящих от сервера. Для этого Puppeteer позволяет подписываться на событие response. Этот метод используется для анализа и модификации данных, которые приходят в ответ на запросы.

Пример обработки сетевых ответов:

page.on('response', response => {
  const url = response.url();
  
  // Логируем ответы только для запросов к API
  if (url.includes('/api/')) {
    console.log('Ответ от API:', response.status());
  }
});

В этом примере мы анализируем все ответы от серверов, чьи URL содержат подстроку /api/, и логируем их статус.

Завершение запроса

Если необходимо изменить поведение запроса, например, изменить его URL или тип, можно воспользоваться методом request.respond(). Это позволяет полностью заменить запрос на новый ответ.

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

page.on('request', request => {
  const url = request.url();
  
  if (url.includes('example.com/old-resource')) {
    request.respond({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({ message: 'Заменённый ответ' })
    });
  } else {
    request.continue();
  }
});

В этом примере для определённого URL ответ на запрос заменяется на заранее заданный JSON-объект.

Заключение

Фильтрация запросов по типу и URL является важной частью тестирования и автоматизации с использованием Puppeteer. Она позволяет не только блокировать нежелательные запросы, но и манипулировать поведением страницы, изменяя или подменяя сетевые ответы. Управление сетевыми запросами помогает ускорить тесты, уменьшить зависимость от внешних сервисов и контролировать поведение приложения на более глубоком уровне.