С чего начать
Используйте dispatcher для одного вызова fetch, чтобы прокси был задан явно, а другие сетевые клиенты в вашем процессе сохранили собственную конфигурацию.
Выберите совместимую среду выполнения и dispatcher
Этот серверный пример рассчитан на Node.js 24 и Undici 7. В отдельном примерном проекте выполните npm install undici@7. Встроенный fetch в Node принимает dispatcher, совместимый с Undici. Это отличается от fetch в браузере, где JavaScript страницы не может выбрать произвольный системный прокси.
Укажите в PROXY_URL документированный провайдером HTTP(S)-шлюз, например намеренно нерабочий https://proxy.example.invalid:8443. Передавайте PROXY_USERNAME и PROXY_PASSWORD через менеджер секретов вашего развёртывания. Не помещайте учётные данные шлюза во фронтенд-код.
Держите аутентификацию на прокси в dispatcher
Сохраните как proxy-check.mjs и запустите node proxy-check.mjs. Токен Basic принадлежит агенту прокси, а не заголовку Authorization целевого сервера. У запроса есть 30-секундный крайний срок через abort, и он не следует редиректам автоматически.
proxy-check.mjs · Node.js 24 + Undici 7
import { ProxyAgent } from 'undici';
function required(name) {
const value = process.env[name];
if (!value) throw new Error('Missing environment variable: ' + name);
return value;
}
const gateway = new URL(required('PROXY_URL'));
if (!['http:', 'https:'].includes(gateway.protocol) || gateway.username || gateway.password) {
throw new Error('Use a credential-free HTTP(S) proxy URL');
}
const credentials = required('PROXY_USERNAME') + ':' + required('PROXY_PASSWORD');
const dispatcher = new ProxyAgent({
uri: gateway.href,
token: 'Basic ' + Buffer.from(credentials).toString('base64'),
});
try {
const response = await fetch('https://example.com/', {
dispatcher,
signal: AbortSignal.timeout(30_000),
redirect: 'manual',
});
await response.body?.cancel();
if (!response.ok) throw new Error('Destination HTTP ' + response.status);
console.log({ status: response.status });
} finally {
await dispatcher.close();
}От диагностики к воркеру
Этот скрипт намеренно отменяет тело ответа, потому что диагностике нужен только статус. Воркер, который использует результат, должен прочитать тело в пределах своего бюджета. Всегда читайте или отменяйте его, прежде чем двигаться дальше, и закрывайте dispatcher при остановке воркера.
Для повторяющихся заданий переиспользуйте один dispatcher с ограниченной параллельностью вместо создания нового на каждый запрос. Держите крайний срок каждого задания отдельным. Не устанавливайте dispatcher на весь процесс, если изменение маршрутизации у каждого затронутого клиента не является намеренным.
- HTTP-ошибка — это ответ; fetch не отклоняет промис лишь потому, что статус 4xx или 5xx.
- Отказ на этапе CONNECT может проявиться как сбой fetch ещё до того, как появится Response от целевого сервера.
- Фиксируйте очищенные категории ошибок; не логируйте токен Basic или полные URL с учётными данными.
Перед выпуском
- Используйте документированные мажорные версии Node и Undici.
- Передавайте dispatcher явно.
- Читайте или отменяйте тела ответов и закрывайте агент.
Источники и дополнительное чтение
Технические материалы, использованные при подготовке руководства. Сверяйтесь с документацией вашей версии и с поддерживаемой конфигурацией вашего провайдера.