إعداد بروكسي في Node.js، توصيل بروكسي HTTP وSOCKS5 بـ fetch و https
يشرح هذا الدليل كيفية توصيل بروكسي HTTP من Socks5Proxy باستخدام ProxyAgent من undici، وبروكسي SOCKS5 باستخدام socks-proxy-agent في Node.js 18 أو أعلى، وكود لاستلام القوائم من API وتناوبها.
ما الذي تحتاجه لاستخدام البروكسي في Node.js؟
يعمل fetch المدمج في Node.js باستخدام مكتبة تسمى undici ولا يقرأ إعدادات البروكسي افتراضيًا. لذلك، يتم استخدام ProxyAgent من undici كـ dispatcher لبروكسي HTTP، بينما يتم استخدام socks-proxy-agent كـ agent لبروكسي SOCKS5 في وحدة https الخاصة بـ Node.
يستخدم المثال عنوان IP 198.51.100.23 ومنفذ HTTP 8000 ومنفذ SOCKS5 1080 واسم المستخدم spx_user وكلمة المرور spx_pass. جميع الأكواد بصيغة ES Module (.mjs).
npm install undici socks-proxy-agentكيفية الاتصال ببروكسي HTTP باستخدام fetch؟
أضف عنوان البروكسي إلى ProxyAgent، واسم المستخدم وكلمة المرور كقيمة مصادقة Basic في خيار token. عند تمريره كـ dispatcher إلى fetch المستورد من undici، يمر الطلب عبر البروكسي. يتم نقل عناوين HTTPS بطريقة CONNECT مشفرة.
إعادة استخدام نفس ProxyAgent لطلبات متعددة يعيد استخدام الاتصالات ويجعلها أسرع. يمكنك إنشاء وكيل واحد لكل بروكسي واستخدامه بالتناوب.
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 IPكيف يتم الاتصال ببروكسي SOCKS5؟
socks-proxy-agent هو وكيل يستخدم مع وحدات http و https في Node. استخدام socks5h يحل أسماء النطاقات عبر الوكيل. يوضح المثال أدناه كيفية تمرير الوكيل إلى https.get وجمع نص الاستجابة.
يمكن إضافة نفس الوكيل إلى httpAgent وhttpsAgent في المكتبات التي تعتمد على وحدة http.
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));كيفية استلام القائمة عبر API وتدويرها؟
عند البدء، يمكنك الحصول على القائمة عبر API وإنشاء وكيل لكل بروكسي واستخدام الوكيل التالي لكل طلب. الكود التالي يحصل على قائمة HTTP بتنسيق ip:port:user:pass وينشئ مصفوفة ProxyAgent، وإذا فشل، يعيد المحاولة مع البروكسي التالي.
أضف حدًا زمنيًا باستخدام AbortSignal.timeout لكل طلب. إذا تراكمت الطلبات دون استجابة، سيتباطأ العمل بأكمله.
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);كيف يتغير الكود عند استخدام تفويض IP؟
قم بتسجيل IPv4 لخادم Node.js في لوحة التحكم، ثم استخدم ProxyAgent مع عنوان IP فقط دون الحاجة إلى token. يمكنك أيضًا استخدام SOCKS5 بدون اسم مستخدم وكلمة مرور مثل socks5h://198.51.100.23:1080. هذا يسهل النشر على عدة خوادم دون الحاجة إلى تخزين كلمات المرور في متغيرات البيئة أو الأكواد.
كيفية الاتصال باستخدام axios؟
axios يعمل على وحدات http وhttps في Node، ويتطلب إضافة وكيل SOCKS5 عبر socks-proxy-agent.
يمكن أيضًا استخدام خيار proxy في axios لإدخال host و port و auth، ولكن في حالة عناوين HTTPS، يكون استخدام وكيل أكثر استقرارًا. استخدام حزمة https-proxy-agent يسمح بتوصيل HTTP بروكسي بنفس الهيكل.
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);ما الذي يجب مراعاته عند إرسال عدة طلبات في نفس الوقت؟
إذا بدأت آلاف الطلبات دفعة واحدة باستخدام Promise.all، فسيؤدي فتح الكثير من الاتصالات إلى إثقال كلا من البروكسي والموقع المستهدف. اضبط حدًا لعدد الطلبات المتزامنة واستخدم قائمة انتظار للتشغيل. يمكنك إنشاء دالة صغيرة لهذا الغرض أو استخدام حزمة مثل p-limit.
توزيع عدد الاتصالات المتزامنة بشكل متساوٍ على كل بروكسي يمنع تراكم الطلبات على IP واحد. الخطة المشتركة تتضمن 500 اتصال متزامن، لذا يرجى ضبط إجمالي عدد الطلبات المتزامنة ضمن هذا الحد.
هل يمكن تطبيق البروكسي على جميع الطلبات باستخدام متغيرات البيئة؟
يقرأ EnvHttpProxyAgent من undici متغيرات البيئة HTTP_PROXY و HTTPS_PROXY و NO_PROVPN لتحديد الوكيل. تسجيله باستخدام setGlobalDispatcher يطبق الوكيل على جميع عمليات fetch في العملية، مما يسهل استخدامه مع مكتبات متعددة.
الإعدادات العامة تستخدم نفس IP لجميع الطلبات، مما يجعلها مناسبة للأدوات أو الاختبارات التي تتطلب الوصول من دولة واحدة بدلاً من جمع البيانات الذي يتطلب تقسيم IP. إذا كنت بحاجة إلى التناوب، قم بتمرير dispatcher مع كل طلب كما رأيت سابقًا.
// 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());كيف يتم حل المشكلات الشائعة؟
إذا بدا أن dispatcher يتم تجاهله عند تمريره إلى fetch المدمج في Node.js، فتأكد من استيراد fetch من حزمة undici. إذا اختلفت إصدارات fetch المدمج وundici المثبت، فقد لا يتطابق الوكيل، لذا فإن أفضل طريقة هي استيراد fetch وProxyAgent من نفس الحزمة.
الاستجابة 407 تعني أن معلومات المصادقة غير صحيحة. تحقق من أن القيمة token تحتوي على اسم المستخدم:كلمة المرور بعد Basic محولة إلى base64. ECONNREFUSED غالبًا ما يكون بسبب خطأ في المنفذ. استخدم منفذ HTTP للوكيل HTTP ومنفذ SOCKS5 للوكيل SOCKS.
- fetch و ProxyAgent موجودان في نفس حزمة undici
- 407: تحقق من قيمة token والـ IP المسجل
- ECONNREFUSED: التمييز بين منفذ HTTP ومنفذ SOCKS5
- حد زمني لجميع الطلبات