Torna al blog

Configurazione del proxy nelle applicazioni Node.js: guida completa con esempi di codice

Guida dettagliata all'integrazione dei proxy in Node.js: dalla configurazione di base a tecniche avanzate di rotazione degli IP e gestione degli errori.

📅14 febbraio 2026
```html

Nello sviluppo di applicazioni Node.js per il parsing, l'automazione o il lavoro con API, spesso sorge la necessità di utilizzare server proxy. Questo consente di aggirare le restrizioni geografiche, distribuire il carico e evitare blocchi per IP. In questa guida esamineremo tutti i modi per configurare un proxy in Node.js, dalle tecniche di base a quelle avanzate con rotazione e gestione degli errori.

Concetti di base sul lavoro con i proxy in Node.js

Un server proxy in Node.js funziona come intermediario tra la tua applicazione e il server di destinazione. Quando invii una richiesta HTTP tramite un proxy, la tua applicazione si connette prima al server proxy, che poi reindirizza la richiesta all'indirizzo finale. Questo consente di nascondere il vero indirizzo IP del tuo server e utilizzare l'indirizzo IP del proxy.

In Node.js ci sono diversi modi principali per lavorare con i proxy a seconda della libreria utilizzata per le richieste HTTP. Le opzioni più popolari sono:

  • Moduli integrati http/https — funzionalità di base senza dipendenze aggiuntive
  • Axios — libreria popolare con un'API conveniente e supporto per le promesse
  • Got — alternativa moderna con supporto per TypeScript
  • node-fetch — implementazione dell'API Fetch per Node.js
  • request — libreria obsoleta ma ancora utilizzata (non raccomandata per nuovi progetti)

I server proxy supportano vari protocolli. Per lavorare con Node.js, i più comuni sono:

Protocollo Descrizione Applicazione
HTTP Protocollo di base per connessioni non crittografate Parsing, lavoro con API senza SSL
HTTPS Proxy con supporto per la crittografia SSL/TLS Connessioni sicure, lavoro con API protette
SOCKS5 Protocollo universale per qualsiasi tipo di traffico WebSocket, UDP, scenari complessi

Per compiti di parsing e automazione, gli sviluppatori utilizzano spesso proxy residenziali, poiché hanno indirizzi IP reali di utenti domestici e raramente vengono bloccati dai siti di destinazione.

Configurazione del proxy tramite il modulo http/https integrato

Node.js fornisce moduli integrati http e https per lavorare con le richieste HTTP. Per connettere un proxy, puoi utilizzare la libreria http-proxy-agent o https-proxy-agent.

Prima di tutto, installa i pacchetti necessari:

npm install http-proxy-agent https-proxy-agent

Ecco un esempio di utilizzo di un proxy HTTP con il modulo integrato:

const http = require('http');
const { HttpProxyAgent } = require('http-proxy-agent');

// Impostazioni del proxy
const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpProxyAgent(proxyUrl);

// Opzioni della richiesta
const options = {
  hostname: 'api.example.com',
  path: '/endpoint',
  method: 'GET',
  agent: agent,
  headers: {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
  }
};

// Esecuzione della richiesta
const req = http.request(options, (res) => {
  let data = '';
  
  res.on('data', (chunk) => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('Risposta:', data);
  });
});

req.on('error', (error) => {
  console.error('Richiesta fallita:', error.message);
});

req.end();

Per le connessioni HTTPS, utilizza https-proxy-agent:

const https = require('https');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);

const options = {
  hostname: 'api.example.com',
  path: '/secure-endpoint',
  method: 'GET',
  agent: agent
};

https.get(options, (res) => {
  let data = '';
  
  res.on('data', (chunk) => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('Risposta sicura:', data);
  });
}).on('error', (error) => {
  console.error('Richiesta HTTPS fallita:', error.message);
});

Questo approccio offre il massimo controllo sulle richieste, ma richiede più codice per gestire le promesse e gli errori. Per la maggior parte dei compiti, è più conveniente utilizzare librerie specializzate.

Lavorare con i proxy nella libreria Axios

Axios è una delle librerie più popolari per le richieste HTTP in Node.js. Fornisce un'API conveniente per configurare i proxy e gestisce automaticamente le promesse.

Installazione di Axios:

npm install axios

La configurazione di base del proxy in Axios appare come segue:

const axios = require('axios');

// Metodo 1: Configurazione del proxy nella richiesta
axios.get('https://api.example.com/data', {
  proxy: {
    protocol: 'http',
    host: 'proxy-server.com',
    port: 8080,
    auth: {
      username: 'your-username',
      password: 'your-password'
    }
  }
})
.then(response => {
  console.log('Dati:', response.data);
})
.catch(error => {
  console.error('Errore:', error.message);
});

Per riutilizzare più volte le stesse impostazioni del proxy, è conveniente creare un'istanza di Axios con la configurazione preimpostata:

const axios = require('axios');

// Creazione di un'istanza con le impostazioni del proxy
const axiosWithProxy = axios.create({
  proxy: {
    protocol: 'http',
    host: 'proxy-server.com',
    port: 8080,
    auth: {
      username: 'your-username',
      password: 'your-password'
    }
  },
  timeout: 10000,
  headers: {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
  }
});

// Utilizzo dell'istanza
async function fetchData() {
  try {
    const response = await axiosWithProxy.get('https://api.example.com/data');
    console.log('Risposta:', response.data);
    return response.data;
  } catch (error) {
    console.error('Richiesta fallita:', error.message);
    throw error;
  }
}

fetchData();

Per lavorare con i proxy HTTPS tramite il metodo CONNECT, puoi utilizzare agenti aggiuntivi:

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy-server.com:8080';
const httpsAgent = new HttpsProxyAgent(proxyUrl);

const axiosInstance = axios.create({
  httpsAgent: httpsAgent,
  timeout: 15000
});

// Utilizzo
axiosInstance.get('https://api.example.com/secure-data')
  .then(response => console.log(response.data))
  .catch(error => console.error(error.message));

Axios gestisce automaticamente il reindirizzamento e supporta gli interceptor per il logging e la gestione degli errori, rendendolo una scelta eccellente per progetti con un uso attivo dei proxy.

Configurazione del proxy in got e node-fetch

Got è un'alternativa moderna ad Axios con un'ottima supporto per TypeScript e avanzate capacità di gestione degli errori. Node-fetch implementa l'API Fetch standard per Node.js.

Lavorare con i proxy in Got

Installazione di Got e degli agenti necessari:

npm install got https-proxy-agent

Ecco un esempio di configurazione del proxy in Got:

const got = require('got');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = {
  https: new HttpsProxyAgent(proxyUrl)
};

// Creazione di un'istanza Got con il proxy
const gotWithProxy = got.extend({
  agent: agent,
  timeout: {
    request: 10000
  },
  retry: {
    limit: 3,
    methods: ['GET', 'POST']
  }
});

// Utilizzo
async function fetchWithGot() {
  try {
    const response = await gotWithProxy('https://api.example.com/data');
    console.log('Risposta:', JSON.parse(response.body));
  } catch (error) {
    console.error('Richiesta Got fallita:', error.message);
  }
}

fetchWithGot();

Lavorare con i proxy in node-fetch

Node-fetch richiede una configurazione esplicita dell'agente per lavorare con i proxy:

npm install node-fetch https-proxy-agent
const fetch = require('node-fetch');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);

async function fetchWithProxy() {
  try {
    const response = await fetch('https://api.example.com/data', {
      agent: agent,
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
      }
    });
    
    if (!response.ok) {
      throw new Error(`Errore HTTP! stato: ${response.status}`);
    }
    
    const data = await response.json();
    console.log('Dati:', data);
    return data;
  } catch (error) {
    console.error('Fetch fallito:', error.message);
    throw error;
  }
}

fetchWithProxy();

Got fornisce funzionalità più ricche di default (ripetizioni automatiche, timeout, gestione degli errori), mentre node-fetch è più vicino all'API Fetch standard ed è adatto per gli sviluppatori familiari con JavaScript del browser.

Collegamento a un proxy SOCKS5 tramite socks-proxy-agent

SOCKS5 è un protocollo proxy universale che funziona a un livello più basso rispetto a HTTP/HTTPS. Supporta qualsiasi tipo di traffico, comprese le connessioni UDP e WebSocket. Per lavorare con SOCKS5 in Node.js, si utilizza la libreria socks-proxy-agent.

Installazione dei pacchetti necessari:

npm install socks-proxy-agent

Ecco un esempio di utilizzo di un proxy SOCKS5 con diverse librerie:

const { SocksProxyAgent } = require('socks-proxy-agent');
const https = require('https');

// Impostazione del proxy SOCKS5 con autorizzazione
const proxyUrl = 'socks5://username:password@proxy-server.com:1080';
const agent = new SocksProxyAgent(proxyUrl);

const options = {
  hostname: 'api.example.com',
  path: '/endpoint',
  method: 'GET',
  agent: agent
};

https.get(options, (res) => {
  let data = '';
  
  res.on('data', (chunk) => {
    data += chunk;
  });
  
  res.on('end', () => {
    console.log('Risposta SOCKS5:', data);
  });
}).on('error', (error) => {
  console.error('Richiesta SOCKS5 fallita:', error.message);
});

Utilizzo di SOCKS5 con Axios:

const axios = require('axios');
const { SocksProxyAgent } = require('socks-proxy-agent');

const proxyUrl = 'socks5://username:password@proxy-server.com:1080';
const httpsAgent = new SocksProxyAgent(proxyUrl);
const httpAgent = new SocksProxyAgent(proxyUrl);

const axiosWithSocks = axios.create({
  httpAgent: httpAgent,
  httpsAgent: httpsAgent,
  timeout: 15000
});

async function fetchViaSocks5() {
  try {
    const response = await axiosWithSocks.get('https://api.example.com/data');
    console.log('Dati tramite SOCKS5:', response.data);
    return response.data;
  } catch (error) {
    console.error('Errore richiesta SOCKS5:', error.message);
    throw error;
  }
}

fetchViaSocks5();

I proxy SOCKS5 sono particolarmente utili per compiti che richiedono di lavorare con protocolli non standard o quando è necessaria la massima flessibilità. Molti fornitori offrono proxy mobili con supporto SOCKS5, consentendo di emulare il traffico mobile per lavorare con API mobili.

Implementazione della rotazione dei proxy per distribuire il carico

Durante il parsing di grandi volumi di dati o il lavoro con API che hanno limiti sul numero di richieste da un singolo IP, è necessario utilizzare la rotazione dei proxy. Questo consente di distribuire le richieste tra più server proxy e evitare blocchi.

Ecco un esempio di implementazione di una semplice rotazione dei proxy:

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

class ProxyRotator {
  constructor(proxyList) {
    this.proxyList = proxyList;
    this.currentIndex = 0;
  }
  
  // Ottenere il prossimo proxy in modo circolare
  getNextProxy() {
    const proxy = this.proxyList[this.currentIndex];
    this.currentIndex = (this.currentIndex + 1) % this.proxyList.length;
    return proxy;
  }
  
  // Ottenere un proxy casuale
  getRandomProxy() {
    const randomIndex = Math.floor(Math.random() * this.proxyList.length);
    return this.proxyList[randomIndex];
  }
  
  // Creare un'istanza Axios con il proxy attuale
  createAxiosInstance(useRandom = false) {
    const proxyUrl = useRandom ? this.getRandomProxy() : this.getNextProxy();
    const agent = new HttpsProxyAgent(proxyUrl);
    
    return axios.create({
      httpsAgent: agent,
      timeout: 10000,
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
      }
    });
  }
}

// Elenco dei proxy
const proxyList = [
  'http://user1:pass1@proxy1.example.com:8080',
  'http://user2:pass2@proxy2.example.com:8080',
  'http://user3:pass3@proxy3.example.com:8080',
  'http://user4:pass4@proxy4.example.com:8080'
];

const rotator = new ProxyRotator(proxyList);

// Utilizzo della rotazione
async function fetchWithRotation(url) {
  const axiosInstance = rotator.createAxiosInstance();
  
  try {
    const response = await axiosInstance.get(url);
    console.log('Successo con il proxy');
    return response.data;
  } catch (error) {
    console.error('Richiesta fallita:', error.message);
    throw error;
  }
}

// Esempio di parsing massivo con rotazione
async function massiveParsing(urls) {
  const results = [];
  
  for (const url of urls) {
    try {
      const data = await fetchWithRotation(url);
      results.push({ url, success: true, data });
      
      // Ritardo tra le richieste
      await new Promise(resolve => setTimeout(resolve, 1000));
    } catch (error) {
      results.push({ url, success: false, error: error.message });
    }
  }
  
  return results;
}

// Avvio del parsing
const urlsToParse = [
  'https://api.example.com/data/1',
  'https://api.example.com/data/2',
  'https://api.example.com/data/3',
  'https://api.example.com/data/4',
  'https://api.example.com/data/5'
];

massiveParsing(urlsToParse)
  .then(results => console.log('Risultati del parsing:', results))
  .catch(error => console.error('Errore nel parsing:', error));

Un esempio più avanzato con monitoraggio dello stato dei proxy e esclusione automatica di quelli non funzionanti:

class AdvancedProxyRotator {
  constructor(proxyList, maxFailures = 3) {
    this.proxyList = proxyList.map(url => ({
      url,
      failures: 0,
      active: true,
      lastUsed: null
    }));
    this.maxFailures = maxFailures;
    this.currentIndex = 0;
  }
  
  // Ottenere un proxy attivo
  getActiveProxy() {
    const activeProxies = this.proxyList.filter(p => p.active);
    
    if (activeProxies.length === 0) {
      throw new Error('Nessun proxy attivo disponibile');
    }
    
    // Trovare il proxy che non è stato utilizzato da più tempo
    const proxy = activeProxies.reduce((oldest, current) => {
      if (!oldest.lastUsed) return oldest;
      if (!current.lastUsed) return current;
      return current.lastUsed < oldest.lastUsed ? current : oldest;
    });
    
    proxy.lastUsed = Date.now();
    return proxy;
  }
  
  // Segnare un proxy come riuscito
  markSuccess(proxyUrl) {
    const proxy = this.proxyList.find(p => p.url === proxyUrl);
    if (proxy) {
      proxy.failures = 0;
    }
  }
  
  // Segnare un proxy come fallito
  markFailure(proxyUrl) {
    const proxy = this.proxyList.find(p => p.url === proxyUrl);
    if (proxy) {
      proxy.failures++;
      if (proxy.failures >= this.maxFailures) {
        proxy.active = false;
        console.warn(`Proxy ${proxyUrl} disattivato dopo ${proxy.failures} fallimenti`);
      }
    }
  }
  
  // Creare un'istanza Axios con rotazione
  async createAxiosInstance() {
    const proxy = this.getActiveProxy();
    const agent = new HttpsProxyAgent(proxy.url);
    
    return {
      instance: axios.create({
        httpsAgent: agent,
        timeout: 10000
      }),
      proxyUrl: proxy.url
    };
  }
  
  // Ottenere statistiche sui proxy
  getStats() {
    return {
      total: this.proxyList.length,
      active: this.proxyList.filter(p => p.active).length,
      inactive: this.proxyList.filter(p => !p.active).length,
      proxies: this.proxyList.map(p => ({
        url: p.url.replace(/\/\/.*@/, '//***@'), // Nascondere le credenziali
        active: p.active,
        failures: p.failures
      }))
    };
  }
}

// Utilizzo del rotatore avanzato
const advancedRotator = new AdvancedProxyRotator(proxyList);

async function fetchWithAdvancedRotation(url) {
  const { instance, proxyUrl } = await advancedRotator.createAxiosInstance();
  
  try {
    const response = await instance.get(url);
    advancedRotator.markSuccess(proxyUrl);
    return response.data;
  } catch (error) {
    advancedRotator.markFailure(proxyUrl);
    throw error;
  }
}

// Output periodico delle statistiche
setInterval(() => {
  console.log('Statistiche proxy:', advancedRotator.getStats());
}, 30000);

Questo sistema esclude automaticamente i proxy non funzionanti dalla rotazione e distribuisce uniformemente il carico tra i server attivi. Questo è fondamentale quando si lavora con grandi volumi di dati.

Gestione degli errori e commutazione automatica dei proxy

Quando si lavora con i proxy, si verificano inevitabilmente errori: timeout, rifiuti di connessione, blocchi da parte del server di destinazione. Una corretta gestione degli errori e la commutazione automatica a un altro proxy aumentano l'affidabilità dell'applicazione.

Ecco un esempio di implementazione di un sistema con ripetizioni automatiche e commutazione dei proxy:

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

class ResilientProxyClient {
  constructor(proxyList, maxRetries = 3) {
    this.proxyList = proxyList;
    this.maxRetries = maxRetries;
    this.currentProxyIndex = 0;
  }
  
  // Ottenere il prossimo proxy
  getNextProxy() {
    const proxy = this.proxyList[this.currentProxyIndex];
    this.currentProxyIndex = (this.currentProxyIndex + 1) % this.proxyList.length;
    return proxy;
  }
  
  // Determinare il tipo di errore
  isRetryableError(error) {
    // Errori per cui vale la pena ripetere la richiesta
    const retryableCodes = ['ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED'];
    const retryableStatuses = [408, 429, 500, 502, 503, 504];
    
    if (error.code && retryableCodes.includes(error.code)) {
      return true;
    }
    
    if (error.response && retryableStatuses.includes(error.response.status)) {
      return true;
    }
    
    return false;
  }
  
  // Eseguire una richiesta con ripetizioni automatiche
  async request(url, options = {}, attempt = 1) {
    const proxyUrl = this.getNextProxy();
    const agent = new HttpsProxyAgent(proxyUrl);
    
    const config = {
      ...options,
      httpsAgent: agent,
      timeout: 10000,
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        ...options.headers
      }
    };
    
    try {
      console.log(`Tentativo ${attempt}/${this.maxRetries} con proxy: ${proxyUrl.replace(/\/\/.*@/, '//***@')}`);
      const response = await axios.get(url, config);
      console.log(`Successo al tentativo ${attempt}`);
      return response.data;
    } catch (error) {
      console.error(`Tentativo ${attempt} fallito: ${error.message}`);
      
      // Se è stato raggiunto il limite di ripetizioni
      if (attempt >= this.maxRetries) {
        console.error(`Massimo tentativi (${this.maxRetries}) raggiunto per ${url}`);
        throw error;
      }
      
      // Se l'errore non è ripetibile
      if (!this.isRetryableError(error)) {
        console.error(`Errore non ripetibile: ${error.message}`);
        throw error;
      }
      
      // Ritardo esponenziale prima della ripetizione
      const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
      console.log(`Attesa di ${delay}ms prima di ripetere...`);
      await new Promise(resolve => setTimeout(resolve, delay));
      
      // Ripetizione ricorsiva con il prossimo proxy
      return this.request(url, options, attempt + 1);
    }
  }
  
  // Elaborazione batch di URL con gestione degli errori
  async batchRequest(urls, concurrency = 3) {
    const results = [];
    const queue = [...urls];
    const active = [];
    
    while (queue.length > 0 || active.length > 0) {
      // Avviare nuove attività fino a raggiungere il limite di concorrenza
      while (active.length < concurrency && queue.length > 0) {
        const url = queue.shift();
        const promise = this.request(url)
          .then(data => ({ url, success: true, data }))
          .catch(error => ({ url, success: false, error: error.message }))
          .finally(() => {
            const index = active.indexOf(promise);
            if (index > -1) active.splice(index, 1);
          });
        
        active.push(promise);
      }
      
      // Attendere il completamento di almeno un'attività
      if (active.length > 0) {
        const result = await Promise.race(active);
        results.push(result);
      }
    }
    
    return results;
  }
}

// Utilizzo
const proxyList = [
  'http://user1:pass1@proxy1.example.com:8080',
  'http://user2:pass2@proxy2.example.com:8080',
  'http://user3:pass3@proxy3.example.com:8080'
];

const client = new ResilientProxyClient(proxyList, 3);

// Richiesta singola
client.request('https://api.example.com/data')
  .then(data => console.log('Dati:', data))
  .catch(error => console.error('Errore finale:', error.message));

// Elaborazione batch
const urls = [
  'https://api.example.com/data/1',
  'https://api.example.com/data/2',
  'https://api.example.com/data/3',
  'https://api.example.com/data/4',
  'https://api.example.com/data/5'
];

client.batchRequest(urls, 3)
  .then(results => {
    const successful = results.filter(r => r.success).length;
    const failed = results.filter(r => !r.success).length;
    console.log(`Completato: ${successful} riusciti, ${failed} falliti`);
    console.log('Risultati:', results);
  });

Questa implementazione include:

  • Commutazione automatica al prossimo proxy in caso di errore
  • Ritardo esponenziale tra le ripetizioni (1s, 2s, 4s, 8s, max 10s)
  • Determinazione del tipo di errore per prendere decisioni sulla ripetizione
  • Controllo della concorrenza durante l'elaborazione batch
  • Logging dettagliato per il debug

Migliori pratiche e ottimizzazione delle prestazioni

Quando si lavora con i proxy nelle applicazioni Node.js, è consigliabile seguire le seguenti raccomandazioni per garantire stabilità e prestazioni:

1. Gestione delle connessioni

Riutilizza gli agenti HTTP invece di crearne di nuovi per ogni richiesta. Questo riduce l'overhead per l'instaurazione della connessione:

const { HttpsProxyAgent } = require('https-proxy-agent');

// Male: creazione di un agente per ogni richiesta
async function badExample(url) {
  const agent = new HttpsProxyAgent(proxyUrl);
  return axios.get(url, { httpsAgent: agent });
}

// Bene: riutilizzo dell'agente
const agent = new HttpsProxyAgent(proxyUrl);
const axiosInstance = axios.create({
  httpsAgent: agent,
  httpAgent: agent
});

async function goodExample(url) {
  return axiosInstance.get(url);
}

2. Impostazione dei timeout

Imposta sempre timeout ragionevoli per evitare che l'applicazione si blocchi:

const axiosInstance = axios.create({
  httpsAgent: agent,
  timeout: 10000, // Timeout generale
  // Impostazione dettagliata dei timeout per Got
  // timeout: {
  //   lookup: 1000,    // Ricerca DNS
  //   connect: 2000,   // Connessione al proxy
  //   secureConnect: 2000, // Handshake SSL
  //   socket: 5000,    // Inattività del socket
  //   response: 3000,  // Attesa del primo byte di risposta
  //   send: 10000,     // Invio della richiesta
  //   request: 15000   // Intera richiesta
  // }
});

3. Controllo della concorrenza

Limita il numero di richieste simultanee per evitare sovraccarichi:

const pLimit = require('p-limit');

// Limitazione a 5 richieste simultanee
const limit = pLimit(5);

async function processUrls(urls) {
  const promises = urls.map(url => 
    limit(() => axiosInstance.get(url))
  );
  
  return Promise.allSettled(promises);
}

4. Rotazione dell'User-Agent

Combina la rotazione dei proxy con la rotazione dell'User-Agent per una maggiore anonimato:

const userAgents = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0'
];

function getRandomUserAgent() {
  return userAgents[Math.floor(Math.random() * userAgents.length)];
}

async function fetchWithRandomUA(url) {
  return axiosInstance.get(url, {
    headers: {
      'User-Agent': getRandomUserAgent()
    }
  });
}

5. Monitoraggio e logging

Implementa un sistema di monitoraggio per tenere traccia delle prestazioni dei proxy:

class ProxyMonitor {
  constructor() {
    this.stats = new Map();
  }
  
  recordRequest(proxyUrl, success, responseTime) {
    if (!this.stats.has(proxyUrl)) {
      this.stats.set(proxyUrl, {
        total: 0,
        success: 0,
        failed: 0,
        totalResponseTime: 0,
        avgResponseTime: 0
      });
    }
    
    const stat = this.stats.get(proxyUrl);
    stat.total++;
    
    if (success) {
      stat.success++;
      stat.totalResponseTime += responseTime;
      stat.avgResponseTime = stat.totalResponseTime / stat.success;
    } else {
      stat.failed++;
    }
  }
  
  getReport() {
    const report = [];
    
    this.stats.forEach((stat, proxyUrl) => {
      report.push({
        proxy: proxyUrl.replace(/\/\/.*@/, '//***@'),
        successRate: ((stat.success / stat.total) * 100).toFixed(2) + '%',
        avgResponseTime: stat.avgResponseTime.toFixed(0) + 'ms',
        total: stat.total,
        success: stat.success,
        failed: stat.failed
      });
    });
    
    return report;
  }
}

const monitor = new ProxyMonitor();

// Wrapper per richieste con monitoraggio
async function monitoredRequest(url, proxyUrl) {
  const startTime = Date.now();
  
  try {
    const response = await axiosInstance.get(url);
    const responseTime = Date.now() - startTime;
    monitor.recordRequest(proxyUrl, true, responseTime);
    return response.data;
  } catch (error) {
    const responseTime = Date.now() - startTime;
    monitor.recordRequest(proxyUrl, false, responseTime);
    throw error;
  }
}

// Report periodico
setInterval(() => {
  console.table(monitor.getReport());
}, 60000);

6. Scelta del tipo di proxy

Scegli il tipo di proxy in base al compito:

Compito Tipo raccomandato Motivo
Parsing massivo di dati pubblici Proxy di data center Alta velocità, basso costo
Lavoro con social media e piattaforme protette Proxy residenziali IP reali, basso rischio di blocco
Emulazione del traffico mobile Proxy mobili IP degli operatori mobili
Lavoro con protocolli non standard Proxy SOCKS5 Supporto per qualsiasi traffico

Per compiti che richiedono un alto livello di anonimato e un rischio minimo di blocchi, si raccomanda di utilizzare proxy residenziali. Per il parsing ad alta velocità di grandi volumi di dati, sono adatti proxy di data center.

7. Sicurezza delle credenziali

Non memorizzare mai le credenziali del proxy nel codice. Utilizza variabili d'ambiente:

// file .env
PROXY_HOST=proxy-server.com
PROXY_PORT=8080
PROXY_USERNAME=your-username
PROXY_PASSWORD=your-password

// Nel codice
require('dotenv').config();

const proxyUrl = `http://${process.env.PROXY_USERNAME}:${process.env.PROXY_PASSWORD}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;

// Oppure per l'elenco dei proxy
const proxyList = process.env.PROXY_LIST.split(',').map(proxy => proxy.trim());

Conclusione

Configurare i proxy nelle applicazioni Node.js è un'abilità importante per gli sviluppatori che lavorano con parsing, automazione e integrazione con API esterne. In questa guida abbiamo esaminato tutti i principali modi per lavorare con i proxy: dalla configurazione di base tramite moduli integrati a tecniche avanzate con rotazione, gestione degli errori e monitoraggio.

Punti chiave da ricordare:

  • Scegli la libreria per le richieste HTTP in base al compito: Axios per versatilità, Got per progetti TypeScript, node-fetch per compatibilità con l'API del browser
  • Utilizza proxy SOCKS5 per lavorare con protocolli non standard e massima flessibilità
  • Implementa la rotazione dei proxy per distribuire il carico e evitare blocchi
  • Implementa un sistema di gestione degli errori con ripetizioni automatiche e commutazione dei proxy
  • Monitora le prestazioni dei proxy ed escludi automaticamente quelli non funzionanti
  • Riutilizza gli agenti HTTP e imposta timeout ragionevoli
  • Memorizza le credenziali in variabili d'ambiente, non nel codice

Quando scegli i proxy per le tue applicazioni Node.js, considera la specificità del compito. Per il parsing di piattaforme protette e il lavoro con API sensibili alla reputazione degli IP, ti consigliamo di utilizzare proxy residenziali: offrono un alto livello di anonimato e un rischio minimo di blocchi grazie all'uso di indirizzi IP reali di utenti domestici.

```