Реалізація перехоплення та модифікації HTTP-запитів у браузерному розширенні

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація перехоплення та модифікації HTTP-запитів у браузерному розширенні
Складна
~2-3 робочих дні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація перехоплення та модифікації HTTP-запитів у розширенні браузера

Перехоплення HTTP-запитів — одна з найпотужніших можливостей розширень. Блокувальники реклами, VPN-розширення, прокси-інструменти, інжектори заголовків — усе це будується на chrome.webRequest (MV2) або chrome.declarativeNetRequest (MV3). Перехід на MV3 кардинально змінив підхід.

MV3: declarativeNetRequest

У Manifest V3 динамічна модифікація запитів замінена на декларативні правила. Браузер застосовує правила сам, без виконання JS-коду розширення. Це швидше та безпечніше, але менш гнучко.

{
  "manifest_version": 3,
  "permissions": ["declarativeNetRequest", "declarativeNetRequestWithHostAccess"],
  "host_permissions": ["<all_urls>"],
  "declarative_net_request": {
    "rule_resources": [
      {
        "id": "static-rules",
        "enabled": true,
        "path": "rules/static.json"
      }
    ]
  }
}

Статичні правила

Файл rules/static.json містить масив правил, які застосовуються постійно:

[
  {
    "id": 1,
    "priority": 1,
    "action": { "type": "block" },
    "condition": {
      "urlFilter": "||analytics.example.com^",
      "resourceTypes": ["script", "xmlhttprequest", "image"]
    }
  },
  {
    "id": 2,
    "priority": 2,
    "action": {
      "type": "modifyHeaders",
      "requestHeaders": [
        { "header": "X-Custom-Token", "operation": "set", "value": "my-token" },
        { "header": "Referer", "operation": "remove" }
      ]
    },
    "condition": {
      "urlFilter": "https://api.internal.corp/*",
      "resourceTypes": ["xmlhttprequest"]
    }
  },
  {
    "id": 3,
    "priority": 1,
    "action": {
      "type": "redirect",
      "redirect": { "regexSubstitution": "https://cdn.example.com\\1" }
    },
    "condition": {
      "regexFilter": "^https://slow-cdn\\.com(.*)",
      "resourceTypes": ["image", "media", "font"]
    }
  }
]

Ліміти: максимум 30000 статичних правил сумарно по всім файлам, 5000 включених правил одночасно (можна змінювати динамічно).

Динамічні правила з service worker

Правила можна додавати та видаляти в рантаймі:

// background/sw.js
async function blockDomain(domain) {
  const existingRules = await chrome.declarativeNetRequest.getDynamicRules();
  const maxId = existingRules.reduce((max, r) => Math.max(max, r.id), 0);

  await chrome.declarativeNetRequest.updateDynamicRules({
    addRules: [{
      id: maxId + 1,
      priority: 10,
      action: { type: 'block' },
      condition: {
        urlFilter: `||${domain}^`,
        resourceTypes: [
          'main_frame', 'sub_frame', 'script', 'stylesheet',
          'image', 'xmlhttprequest', 'other'
        ]
      }
    }],
    removeRuleIds: []
  });
}

async function unblockDomain(domain) {
  const rules = await chrome.declarativeNetRequest.getDynamicRules();
  const toRemove = rules
    .filter(r => r.condition.urlFilter === `||${domain}^`)
    .map(r => r.id);

  if (toRemove.length > 0) {
    await chrome.declarativeNetRequest.updateDynamicRules({
      addRules: [],
      removeRuleIds: toRemove
    });
  }
}

// Модифікація заголовків з динамічним значенням
async function setAuthHeader(apiUrl, token) {
  const rules = await chrome.declarativeNetRequest.getDynamicRules();
  const existingRule = rules.find(r =>
    r.condition.urlFilter === apiUrl && r.action.type === 'modifyHeaders'
  );

  const newRule = {
    id: existingRule?.id ?? (rules.reduce((m, r) => Math.max(m, r.id), 0) + 1),
    priority: 5,
    action: {
      type: 'modifyHeaders',
      requestHeaders: [
        { header: 'Authorization', operation: 'set', value: `Bearer ${token}` }
      ]
    },
    condition: {
      urlFilter: apiUrl,
      resourceTypes: ['xmlhttprequest', 'fetch']
    }
  };

  await chrome.declarativeNetRequest.updateDynamicRules({
    addRules: [newRule],
    removeRuleIds: existingRule ? [existingRule.id] : []
  });
}

Спостереження за запитами: chrome.webRequest (лише MV2)

У MV2 можна було перехоплювати запити синхронно та модифікувати їх у JS. У MV3 chrome.webRequest доступний лише в режимі спостереження (без блокування):

// MV2 або MV3 (тільки читання, без blocking)
chrome.webRequest.onCompleted.addListener(
  (details) => {
    if (details.statusCode >= 400) {
      logFailedRequest({
        url: details.url,
        status: details.statusCode,
        tabId: details.tabId,
        timestamp: details.timeStamp
      });
    }
  },
  { urls: ['https://api.your-service.com/*'] },
  ['responseHeaders']
);

chrome.webRequest.onBeforeRequest.addListener(
  (details) => {
    // У MV3 — лише спостереження, без blocking
    analytics.track('request', {
      url: new URL(details.url).pathname,
      method: details.method,
      tabId: details.tabId
    });
  },
  { urls: ['<all_urls>'], types: ['xmlhttprequest'] }
);

Перенаправлення запитів через declarativeNetRequest

Складні редиректи з підстановкою:

// Перенаправити запити до staging на production
await chrome.declarativeNetRequest.updateDynamicRules({
  addRules: [{
    id: 100,
    priority: 1,
    action: {
      type: 'redirect',
      redirect: {
        regexSubstitution: 'https://api.production.com\\1'
      }
    },
    condition: {
      regexFilter: '^https://api\\.staging\\.com(.*)',
      resourceTypes: ['xmlhttprequest', 'fetch']
    }
  }],
  removeRuleIds: []
});

Інъекція заголовків відповіді

З дозволом declarativeNetRequestWithHostAccess можна змінювати заголовки відповіді — наприклад, убирати CORS-обмеження для розробки:

await chrome.declarativeNetRequest.updateDynamicRules({
  addRules: [{
    id: 200,
    priority: 1,
    action: {
      type: 'modifyHeaders',
      responseHeaders: [
        { header: 'Access-Control-Allow-Origin', operation: 'set', value: '*' },
        { header: 'Access-Control-Allow-Methods', operation: 'set', value: 'GET, POST, PUT, DELETE' },
        { header: 'X-Frame-Options', operation: 'remove' }
      ]
    },
    condition: {
      urlFilter: 'https://api.internal.corp/*',
      resourceTypes: ['xmlhttprequest']
    }
  }],
  removeRuleIds: []
});

Відлагодження правил

// Перевірити, які правила застосувалися до останніх запитів
const matched = await chrome.declarativeNetRequest.getMatchedRules({
  tabId: tab.id,
  minTimeStamp: Date.now() - 60000
});
console.log('Застосовані правила:', matched.rulesMatchedInfo);

// Перевірити, сработає ли правило для конкретного URL
const result = await chrome.declarativeNetRequest.testMatchOutcome({
  url: 'https://analytics.example.com/track',
  type: 'xmlhttprequest',
  method: 'GET',
  tabId: -1,
  initiator: 'https://example.com'
});
console.log('Результат:', result.matchedRule); // null або об'єкт правила

Обмеження MV3 та обхідні шляхи

Не можна модифікувати тіло запиту через declarativeNetRequest. Для цього потрібен content script, який перехоплює fetch/XMLHttpRequest через monkey-patching у world: 'MAIN':

// content script з world: 'MAIN'
const originalFetch = window.fetch;
window.fetch = async function(input, init = {}) {
  const url = typeof input === 'string' ? input : input.url;

  if (url.includes('api.target.com')) {
    init.headers = {
      ...init.headers,
      'X-Injected-Header': 'value',
    };

    // Модифікуємо тіло
    if (init.body) {
      const body = JSON.parse(init.body);
      body.extraField = 'injected';
      init.body = JSON.stringify(body);
    }
  }

  return originalFetch.call(this, input, init);
};

Це працює, але має обмеження: monkey-patching не торкається запитів із worker-потоків сторінки і не перехоплює WebSocket.

Для розширень, яким потрібна повна влада над трафіком (корпоративні прокси, інструменти безпеки), MV2 ще доступний за корпоративною політикою Chrome, але не буде підтримуватися у публічному Chrome Web Store.