Konfiguracja proxy w Node.js, podłączanie HTTP i SOCKS5 proxy do fetch i https
Ten przewodnik pokazuje, jak w Node.js 18+ połączyć HTTP proxy Socks5Proxy przez undici ProxyAgent, SOCKS5 przez socks-proxy-agent oraz jak pobierać i rotować listę przez API.
Co jest potrzebne do korzystania z proxy w Node.js?
Wbudowany fetch w Node.js działa na bibliotece undici i domyślnie nie odczytuje ustawień proxy. Dlatego HTTP proxy jest używany przez przekazanie ProxyAgent z undici jako dispatcher, a SOCKS5 proxy jest używany przez przekazanie socks-proxy-agent jako agent do modułu https w Node.js.
Przykładowe dane: IP 198.51.100.23, port HTTP 8000, port SOCKS5 1080, nazwa użytkownika spx_user, hasło spx_pass. Wszystkie przykłady użyły formatu modułów ES (.mjs).
npm install undici socks-proxy-agentJak podłączyć HTTP proxy do fetch?
Podaj adres proxy w ProxyAgent, a nazwę użytkownika i hasło w opcji token jako wartość Basic Auth. Przekaż go jako dispatcher do fetch z undici, a żądanie przejdzie przez proxy. Adresy HTTPS są przekazywane w sposób zaszyfrowany przez CONNECT.
Wielokrotne użycie tego samego ProxyAgent w wielu żądaniach przyspiesza połączenia dzięki ich ponownemu wykorzystaniu. Możesz stworzyć jeden agent na proxy i używać ich rotacyjnie.
import { fetch, ProxyAgent } from "undici";
const agent = new ProxyAgent({
uri: "http://198.51.100.23:8000",
token: "Basic " + Buffer.from("spx_user:spx_pass").toString("base64"),
});
const res = await fetch("https://api.ipify.org?format=json", { dispatcher: agent });
console.log(res.status, await res.json()); // "ip" should be the proxy IPJak połączyć się z proxy SOCKS5?
socks-proxy-agent to agent używany z modułami http i https w Node.js. Użycie socks5h jako adresu powoduje, że rozwiązywanie nazw domen jest wykonywane po stronie proxy. Poniższy przykład przekazuje agenta do https.get i zbiera treść odpowiedzi do wyświetlenia.
Biblioteki działające na module http, takie jak axios, również mogą używać SOCKS5, jeśli przekażesz ten sam agent w httpAgent i httpsAgent.
import https from "node:https";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://spx_user:spx_pass@198.51.100.23:1080");
https.get("https://api.ipify.org?format=json", { agent }, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => console.log(res.statusCode, body));
}).on("error", (err) => console.error("request failed:", err.message));Jak pobrać listę przez API i używać jej w pętli?
Podczas rozpoczęcia pracy pobierz listę przez API i utwórz agenta dla każdego proxy, używając następnego agenta dla każdego żądania. Poniższy kod pobiera listę HTTP w formacie ip:port:user:pass i tworzy tablicę ProxyAgent, a w przypadku niepowodzenia próbuje ponownie z następnym proxy.
Dodaj limit czasu do żądań za pomocą AbortSignal.timeout, aby nie spowalniać całego zadania przez nagromadzenie nieodpowiadających żądań.
import { fetch, ProxyAgent } from "undici";
const API = "https://socks5proxy.io/api/v1";
const KEY = "YOUR_API_KEY";
const text = await (await fetch(API + "/proxies/download?format=ip:port:user:pass&protocol=http", {
headers: { Authorization: "Bearer " + KEY },
})).text();
const agents = text.trim().split("\n").map((line) => {
const [ip, port, user, pass] = line.trim().split(":");
return new ProxyAgent({
uri: "http://" + ip + ":" + port,
token: "Basic " + Buffer.from(user + ":" + pass).toString("base64"),
});
});
let i = 0;
async function get(url, tries = 3) {
for (let t = 0; t < tries; t++) {
const dispatcher = agents[i++ % agents.length];
try {
const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(20000) });
if (res.ok) return await res.text();
} catch {
// try the next proxy
}
}
return null;
}
console.log((await get("https://example.com/"))?.length);Jak zmienia się kod przy użyciu uwierzytelniania IP?
Zarejestruj IPv4 serwera z Node.js w panelu, a w ProxyAgent wystarczy podać adres bez tokenu. SOCKS5 również działa bez loginu, np. socks5h://198.51.100.23:1080. Dzięki temu nie musisz przechowywać haseł w zmiennych środowiskowych ani kodzie, co ułatwia wdrożenie na wielu serwerach.
Jak połączyć się z axios?
axios działa na modułach http i https Node.js, więc można użyć agentów do ustawienia proxy. Dla SOCKS5 użyj socks-proxy-agent w httpAgent i httpsAgent, a opcję proxy w axios ustaw na false, aby uniknąć konfliktu ustawień.
Proxy HTTP można również określić za pomocą opcji proxy w axios, wprowadzając host, port i auth, ale dla adresów HTTPS bardziej stabilne jest użycie agenta. Pakiet https-proxy-agent pozwala na połączenie z proxy HTTP w tej samej strukturze.
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://spx_user:spx_pass@198.51.100.23:1080");
const client = axios.create({ httpAgent: agent, httpsAgent: agent, proxy: false, timeout: 20000 });
const { data } = await client.get("https://api.ipify.org?format=json");
console.log(data);Na co zwrócić uwagę przy wysyłaniu wielu żądań jednocześnie?
Jeśli uruchomisz tysiące żądań jednocześnie przez Promise.all, zbyt wiele połączeń obciąży zarówno proxy, jak i docelową stronę. Ustal limit jednoczesnych żądań i użyj kolejki zadań, aby przetwarzać tylko określoną liczbę na raz. Możesz napisać własną funkcję lub użyć pakietu takiego jak p-limit.
Równomierne rozłożenie liczby równoczesnych połączeń na każde proxy zapobiega przeciążeniu jednego IP. Współdzielone plany obejmują 500 równoczesnych połączeń, więc dostosuj całkowitą liczbę równoczesnych żądań do tego limitu.
Czy można zastosować proxy do wszystkich żądań za pomocą zmiennych środowiskowych?
EnvHttpProxyAgent z undici czyta zmienne środowiskowe HTTP_PROXY, HTTPS_PROXY i NO_PROXY, aby określić proxy. Zarejestruj go za pomocą setGlobalDispatcher, a wszystkie wywołania fetch w tym procesie będą przechodzić przez proxy. Jest to wygodne, gdy wiele bibliotek używa fetch wewnętrznie.
Ustawienia globalne używają tego samego IP dla wszystkich żądań, więc lepiej pasują do narzędzi lub testów wymagających dostępu z jednego kraju niż do zadań zbierania danych wymagających podziału IP. Jeśli potrzebujesz rotacji, przekaż dispatcher dla każdego żądania, jak pokazano wcześniej.
// HTTPS_PROXY=http://spx_user:spx_pass@198.51.100.23:8000 node app.mjs
import { EnvHttpProxyAgent, setGlobalDispatcher, fetch } from "undici";
setGlobalDispatcher(new EnvHttpProxyAgent());
const res = await fetch("https://api.ipify.org");
console.log(await res.text());Jak rozwiązać częste problemy?
Jeśli wydaje się, że dispatcher jest ignorowany w Node.js wbudowanym fetch, sprawdź, czy fetch został zaimportowany z pakietu undici. Jeśli wersje wbudowanego fetch i zainstalowanego undici są różne, agent może nie pasować. Najpewniejszym sposobem jest importowanie zarówno fetch, jak i ProxyAgent z tego samego pakietu.
Odpowiedź 407 oznacza, że dane uwierzytelniające są nieprawidłowe. Sprawdź, czy wartość tokenu zawiera nazwę użytkownika i hasło zakodowane w base64 po słowie Basic. ECONNREFUSED często oznacza, że port jest nieprawidłowy. Użyj portu HTTP dla agenta HTTP i portu SOCKS5 dla agenta SOCKS.
- fetch i ProxyAgent są częścią tego samego pakietu undici
- 407: Sprawdź wartość tokenu i zarejestrowane IP
- ECONNREFUSED: rozróżnienie portu HTTP i SOCKS5
- Limit czasu dla wszystkich żądań