Перейти к содержанию

Руководство · На русском

Прокси в Axios для Node.js: пример и ошибки

Эта инструкция настраивает Axios в Node.js для одного HTTPS-запроса через HTTP-прокси. Явный агент отвечает за CONNECT и авторизацию шлюза. Отдельно проверяются ответ назначения, размер данных и время ожидания. Настройка не предназначена для Axios в браузере.

Каталог и инструкции — на русском. Страница отдельного товара, аккаунт, корзина, оплата и полные условия обслуживания пока доступны на английском.

Опубликовано:

Короткие ответы

Как передать прокси с логином и паролем в Axios?

В показанном варианте HttpsProxyAgent передаётся как httpsAgent, а proxy: false отключает собственный выбор прокси Axios. Выбран HTTP-адаптер Node.js. Исходные секреты поступают из конфигурации процесса, не из опубликованного кода.

Сработает ли этот код во frontend?

Нет. Браузерный JavaScript не задаёт сетевой прокси через httpsAgent. Выполняйте пример на сервере Node.js и не помещайте пароль в frontend-переменные, сборку или ответ клиенту.

Почему HTTPS-запрос использует http://?

Схема описывает соединение до шлюза. CONNECT создаёт туннель, после чего внутри него выполняется TLS с назначением. Сам HTTP-канал до шлюза и его Basic-авторизация этим не шифруются.

Достаточно HTTP 200 для успешной проверки?

Нет. В примере отдельно требуются успешный CONNECT, статус назначения 200 и JSON с корректным IP. Ответ не подтверждает страну, скорость или результат другого сайта.

Зафиксируйте среду и транспорт

Оригинальный пример использует Node.js 22.22.0, Axios 1.20.0 и https-proxy-agent 9.1.0. Это зафиксированная комбинация, а не обещание совместимости любой новой версии. Перед переносом в рабочий проект проверьте его runtime, lockfile и выбранный адаптер; установка зависимостей сама по себе не проверяет сетевой маршрут.

Пакеты и версии исходного примераsh
npm install --save-exact axios@1.20.0 https-proxy-agent@9.1.0
node --version
npm ls axios https-proxy-agent

Официальная конфигурация Axios различает пользовательские агенты, proxy и адаптеры. Здесь явно выбран adapter: http. Переход на fetch-адаптер меняет настройку транспорта; не считайте параметры одного адаптера универсальными для всех.

Подготовьте секреты только для процесса

В Connection builder · English выберите HTTP и копируйте полное имя пользователя с нужными параметрами пула, страны и ротации. Передайте исходные значения как PROXY_USER и PROXY_PASSWORD через свой механизм секретов. PROXY_SERVER при необходимости задаёт только адрес HTTP-шлюза, без встроенных учётных данных.

Не смешивайте назначения полей
ПараметрДля чего нужен
httpsAgentВ этом примере открывает туннель и задаёт его маршрут.
proxy: falseОтключает конкурирующий выбор прокси самим Axios.
PROXY_USER / PROXY_PASSWORDАвторизация шлюза, а не вход на сайт назначения.
auth или Authorization запросаОтносятся к назначению; не место для пароля прокси.
Переменные браузерной сборкиНе должны содержать секрет подключения.

Код кодирует логин и пароль по отдельности ровно один раз. Передавайте исходный пароль, а не уже преобразованный URL. Двоеточие в логине отклоняется из-за разделителя Basic-авторизации. Не печатайте URL агента, весь объект ошибки Axios или его config: внутри могут остаться секреты.

Выполните один ограниченный запрос

Сохраните файл как axios-check.mjs и запустите node axios-check.mjs в подготовленной среде. Назначение берётся из конфигурации руководства. Используйте только разрешённый небольшой ресурс; не заменяйте проверку покупкой, отправкой формы или рабочим запросом с личными данными.

axios-check.mjs — тело исходного примераjavascript
import axios from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { isIP } from 'node:net';

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error('Missing runtime setting');
  return value;
}

async function main() {
  const proxy = new URL(process.env.PROXY_SERVER ?? 'http://gw.portproof.org:7000');
  if (proxy.protocol !== 'http:' || !proxy.hostname || proxy.username ||
      proxy.password || proxy.pathname !== '/' || proxy.search || proxy.hash) {
    throw new Error('Invalid gateway URL');
  }
  const username = required('PROXY_USER');
  if (username.includes(':')) throw new Error('Invalid Basic username');
  proxy.username = encodeURIComponent(username);
  proxy.password = encodeURIComponent(required('PROXY_PASSWORD'));

  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), 20_000);
  const agent = new HttpsProxyAgent(proxy, {
    keepAlive: false, maxSockets: 1, signal: controller.signal,
  });
  let connectStatus;
  agent.on('proxyConnect', (response) => { connectStatus = response.statusCode; });
  try {
    const response = await axios.get('https://api.portproof.org/v1/echo-ip', {
      adapter: 'http', httpsAgent: agent, proxy: false,
      signal: controller.signal, timeout: 10_000,
      maxRedirects: 0, maxContentLength: 65_536, maxBodyLength: 0,
      responseType: 'text', transformResponse: [(body) => body],
      validateStatus: () => true,
    });
    if (connectStatus !== 200) {
      throw new Error('Proxy CONNECT status ' + connectStatus);
    }
    if (response.status !== 200) {
      throw new Error('Destination HTTP status ' + response.status);
    }
    const payload = JSON.parse(response.data);
    if (!payload || typeof payload.ip !== 'string' || !isIP(payload.ip)) {
      throw new Error('Invalid echo JSON');
    }
    console.log('HTTP', response.status, 'exit', payload.ip);
  } catch (error) {
    if (connectStatus && connectStatus !== 200) {
      console.error('Proxy CONNECT status', connectStatus);
    } else if (controller.signal.aborted) {
      console.error('Request deadline exceeded');
    } else if (axios.isAxiosError(error)) {
      console.error('Request failed:', error.code ?? 'AXIOS_ERROR');
    } else {
      console.error(error instanceof SyntaxError ? 'Invalid echo JSON' : error.message);
    }
    process.exitCode = 1;
  } finally {
    clearTimeout(timer);
    controller.abort();
    agent.destroy();
  }
}

main().catch(() => {
  console.error('Check gateway and runtime credential settings');
  process.exitCode = 1;
});

proxyConnect сохраняет ответ на CONNECT отдельно от HTTPS-ответа. Поэтому отказ шлюза не называется ошибкой API. Даже после открытия туннеля назначение должно пройти проверку сертификата и вернуть подходящее содержимое. Равный IP в другом клиенте не заменяет эту проверку маршрута.

Сохраните лимиты и завершение ресурса

Axios ограничивает ожидание десятью секундами, общий AbortController — двадцатью. Сигнал получает и агент, включая ожидание ответа CONNECT. finally отменяет принадлежащее проверке соединение и уничтожает агент. Это бюджеты примера, а не точная гарантия прошедшего времени при любой нагрузке.

Буфер ответа ограничен 64 КиБ, тело запроса не отправляется, перенаправления не выполняются. Лимит ответа не равен списанному трафику: остаются протокольные расходы и буферизация. Для полезной загрузки другого размера задавайте ограничения осознанно и считайте попытки, а не только удачные результаты.

Проверка сертификата включена. В управляемой среде допустимый дополнительный CA задаётся штатным способом до запуска Node.js. Не отключайте проверку TLS для исправления 407 или CONNECT: эти события происходят на другом этапе.

Выберите действие по этапу ошибки

Короткий разбор результата
НаблюдениеСледующая проверка
CONNECT 407Полный логин, пароль и ГБ по диагностике авторизации.
CONNECT 502 или 503Шлюз не открыл туннель; сохранить время и разобрать отказ CONNECT.
HTTP 403 или 429 назначенияПроверить правила доступа или ограничение сервиса; смена пароля шлюза их не исправляет.
ECONNABORTED или deadline exceededУстановить, где закончился бюджет: соединение, заголовки или чтение.
Некорректный JSON или размерСравнить фактическое содержимое с ожидаемой небольшой проверкой.

Переносите настройку в реальный клиент

Если проверка проходит, сделайте один разрешённый запрос рабочим клиентом. Для службы выделите клиент под стабильную конфигурацию и ограничьте очередь: уничтожение одноразового агента не должно отменять чужие задачи. Проверка curl и приложения помогает найти различие процессов; Node fetch имеет отдельный рецепт.

Мобильный и резидентский трафик Portproof используют общий баланс ГБ. Ни агент, ни его keepAlive не резервируют устройство и не гарантируют постоянный IP. Посмотрите актуальные тарифы, если нужна покупка; кабинет и checkout остаются на английском. Документация проверена 31 октября 2026 года, код сохранён из существующего английского руководства; нового теста живого пула, скорости или географии не заявлено.

Допустимое использование

Используйте прокси для разрешённых задач и соблюдайте правила принимающего сервиса. Настройка соединения не даёт права на доступ. Применяются правила допустимого использования · English.

Следующий шаг