UNPKG

@rynn-k/proxy-agent

Version:

Efficient proxy rotation agent for Node.js with seamless axios integration

513 lines (392 loc) • 13.8 kB
# @rynn-k/proxy-agent Efficient proxy rotation agent for Node.js with seamless axios integration. Supports HTTP, HTTPS, SOCKS4, and SOCKS5 proxies with both authenticated and non-authenticated modes, automatic rotation, health checking, and comprehensive error handling. ## šŸš€ Features - āœ… **Smart Proxy Rotation** - Sequential or random proxy selection - āœ… **Multiple Protocol Support** - HTTP, HTTPS, SOCKS4, and SOCKS5 - āœ… **Multiple Auth Types** - Support for authenticated and non-authenticated proxies - āœ… **Axios Integration** - Drop-in replacement for axios HTTP/HTTPS agents - āœ… **Auto Validation** - Built-in IP and port validation - āœ… **Health Checking** - Test proxy connectivity and response times - āœ… **Auto Reload** - Dynamic proxy file reloading - āœ… **Multiple Formats** - Flexible proxy file format support (URL and colon-separated) - āœ… **TypeScript Ready** - Full TypeScript definitions included - āœ… **Minimal Dependencies** - Only requires proxy agent libraries ## šŸ“¦ Installation ```bash npm install @rynn-k/proxy-agent ``` All required dependencies (`https-proxy-agent`, `http-proxy-agent`, `socks-proxy-agent`) will be installed automatically. ## šŸ”§ Quick Start ### 1. Create Proxy File Create `proxies.txt` with your proxy list: ```txt # HTTP/HTTPS proxies (ip:port) 192.168.1.1:8080 10.0.0.1:3128 # SOCKS5 proxies (URL format) socks5://192.168.1.10:1080 socks5://username:password@proxy.example.com:1080 # SOCKS4 proxies socks4://192.168.1.11:1080 # Authenticated HTTP proxies (ip:port:username:password) 192.168.1.2:8080:user123:pass456 proxy.example.com:3128:myuser:mypass # Protocol-specific colon format (protocol:ip:port) http:192.168.1.3:8080 https:secure-proxy.com:8080 socks5:192.168.1.4:1080 # Authenticated with protocol (protocol:ip:port:username:password) http:192.168.1.5:8080:user:pass socks5:192.168.1.6:1080:user:pass ``` ### 2. Basic Usage ```javascript const ProxyAgent = require('@rynn-k/proxy-agent'); const axios = require('axios'); // Initialize proxy agent const proxy = new ProxyAgent('./proxies.txt'); // Use with axios const response = await axios.get('https://httpbin.org/ip', proxy.config()); console.log('Your IP:', response.data.origin); ``` ### 3. Advanced Configuration ```javascript const proxy = new ProxyAgent('./proxies.txt', { random: true, // Random proxy selection (default: false) log: true, // Enable logging (default: true) autoReload: true, // Auto-reload on file change (default: false) encoding: 'utf-8', // File encoding (default: 'utf-8') type: 'socks5' // Default proxy type when not specified (default: 'http') }); ``` ## šŸ“– API Documentation ### Constructor ```javascript new ProxyAgent(proxyFilePath, options) ``` **Parameters:** - `proxyFilePath` (string): Path to proxy file (default: 'proxies.txt') - `options` (object): Configuration options **Options:** - `random` (boolean): Use random proxy selection instead of sequential - `log` (boolean): Enable/disable logging - `autoReload` (boolean): Auto-reload proxy file on changes - `encoding` (string): File encoding for reading proxy file - `type` (string): Default proxy type ('http', 'https', 'socks4', 'socks5') when not specified in proxy string ### Methods #### `config()` Returns axios configuration object with proxy agents configured. ```javascript const response = await axios.get('https://example.com', proxy.config()); ``` #### `https()` Returns HTTPS proxy agent (or SOCKS agent for SOCKS proxies). ```javascript const httpsAgent = proxy.https(); const response = await axios.get('https://example.com', { httpsAgent, proxy: false }); ``` #### `http()` Returns HTTP proxy agent (or SOCKS agent for SOCKS proxies). ```javascript const httpAgent = proxy.http(); ``` #### `getCurrentProxy()` Get information about the currently selected proxy. ```javascript const current = proxy.getCurrentProxy(); console.log(current); // { ip: '192.168.1.1', port: 8080, hasAuth: false, protocol: 'http', index: 0 } ``` #### `test(testUrl, timeout, useCurrentProxy)` Test proxy connectivity and measure response time. ```javascript const result = await proxy.test('https://httpbin.org/ip', 10000); console.log(result); // { success: true, proxy: 'socks5://192.168.1.10:1080', time: 245, data: {...} } ``` **Parameters:** - `testUrl` (string): URL to test (default: 'https://httpbin.org/ip') - `timeout` (number): Request timeout in milliseconds (default: 10000) - `useCurrentProxy` (boolean): Use current proxy or get next (default: true) #### `list()` Get information about all loaded proxies. ```javascript const proxies = proxy.list(); console.log(proxies); // [ // { index: 0, ip: '192.168.1.1', port: 8080, hasAuth: false, protocol: 'http', current: true }, // { index: 1, ip: '192.168.1.10', port: 1080, hasAuth: true, protocol: 'socks5', current: false } // ] ``` #### `stats()` Get proxy agent statistics including protocol distribution. ```javascript const stats = proxy.stats(); console.log(stats); // { // total: 10, // auth: 5, // noAuth: 5, // protocols: { http: 4, https: 2, socks5: 3, socks4: 1 }, // currentIndex: 2, // lastUsedIndex: 1, // random: false, // file: '/path/to/proxies.txt', // autoReload: false, // currentProxy: { ip: '192.168.1.1', port: 8080, hasAuth: false, protocol: 'http', index: 1 } // } ``` #### `reload()` Manually reload proxies from file. ```javascript proxy.reload(); ``` #### `destroy()` Clean up resources and stop file watching. ```javascript proxy.destroy(); ``` ## šŸ’” Usage Examples ### Basic Rotation with SOCKS5 ```javascript const ProxyAgent = require('@rynn-k/proxy-agent'); const axios = require('axios'); // Create proxies.txt with SOCKS5 proxies // socks5://192.168.1.10:1080 // socks5://user:pass@192.168.1.11:1080 const proxy = new ProxyAgent('./proxies.txt'); // Each request uses the next proxy in rotation for (let i = 0; i < 5; i++) { try { const response = await axios.get('https://httpbin.org/ip', proxy.config()); console.log(`Request ${i + 1}:`, response.data.origin); } catch (error) { console.error(`Request ${i + 1} failed:`, error.message); } } ``` ### Mixed Protocol Proxies ```javascript // proxies.txt contains mixed protocols: // http://192.168.1.1:8080 // socks5://192.168.1.10:1080 // socks4://192.168.1.11:1080 // https://secure.proxy.com:8080 const proxy = new ProxyAgent('./proxies.txt', { random: true, // Randomly select from all protocols log: true }); // The agent automatically uses the correct protocol for each proxy const response = await axios.get('https://api.example.com/data', proxy.config()); ``` ### Default Protocol Configuration ```javascript // If your proxies.txt doesn't specify protocols: // 192.168.1.10:1080 // 192.168.1.11:1080 // 192.168.1.12:1080:user:pass // Set default protocol to SOCKS5 const proxy = new ProxyAgent('./proxies.txt', { type: 'socks5', // All proxies without protocol will be treated as SOCKS5 log: true }); const response = await axios.get('https://example.com', proxy.config()); ``` ### Error Handling & Retry with Protocol Fallback ```javascript async function robustRequest(url, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await axios.get(url, { ...proxy.config(), timeout: 10000 }); const currentProxy = proxy.getCurrentProxy(); console.log(`āœ… Success with ${currentProxy.protocol}://${currentProxy.ip}:${currentProxy.port}`); return response.data; } catch (error) { const currentProxy = proxy.getCurrentProxy(); console.log(`āŒ Attempt ${attempt} failed with ${currentProxy.protocol}://${currentProxy.ip}:${currentProxy.port}`); if (attempt === maxRetries) { throw new Error(`All ${maxRetries} attempts failed`); } // Wait before retry with different proxy await new Promise(resolve => setTimeout(resolve, 2000)); } } } // Usage try { const data = await robustRequest('https://api.example.com/data'); console.log(data); } catch (error) { console.error('Request failed after all retries:', error.message); } ``` ### Axios Instance Integration ```javascript const axiosWithProxy = axios.create({ timeout: 15000, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } }); // Add proxy rotation to every request axiosWithProxy.interceptors.request.use(config => { const proxyConfig = proxy.config(); config.httpsAgent = proxyConfig.httpsAgent; config.httpAgent = proxyConfig.httpAgent; config.proxy = false; return config; }); // Now all requests automatically use rotating proxies const response = await axiosWithProxy.get('https://api.example.com/data'); ``` ### Health Checking All Protocols ```javascript // Test all proxies and filter working ones const proxy = new ProxyAgent('./proxies.txt', { log: false }); const workingProxies = []; const failedProxies = []; const allProxies = proxy.list(); for (let i = 0; i < allProxies.length; i++) { const proxyInfo = allProxies[i]; try { const result = await proxy.test('https://httpbin.org/ip', 10000, false); if (result.success) { workingProxies.push({ ...proxyInfo, responseTime: result.time }); console.log(`āœ… ${proxyInfo.protocol}://${proxyInfo.ip}:${proxyInfo.port} - ${result.time}ms`); } else { failedProxies.push(proxyInfo); console.log(`āŒ ${proxyInfo.protocol}://${proxyInfo.ip}:${proxyInfo.port} - ${result.error}`); } } catch (error) { failedProxies.push(proxyInfo); console.log(`āŒ ${proxyInfo.protocol}://${proxyInfo.ip}:${proxyInfo.port} - ${error.message}`); } } console.log(`\nšŸ“Š Results:`); console.log(` Working: ${workingProxies.length}`); console.log(` Failed: ${failedProxies.length}`); // Sort by response time workingProxies.sort((a, b) => a.responseTime - b.responseTime); console.log('\n⚔ Fastest proxies:'); workingProxies.slice(0, 3).forEach(p => { console.log(` ${p.protocol}://${p.ip}:${p.port} - ${p.responseTime}ms`); }); ``` ### Protocol-Specific Usage ```javascript // Use only SOCKS5 proxies for specific tasks const socksProxy = new ProxyAgent('./socks5-proxies.txt', { type: 'socks5' }); // Use only HTTP proxies for other tasks const httpProxy = new ProxyAgent('./http-proxies.txt', { type: 'http' }); // Different requests with different proxy types const socksResponse = await axios.get('https://api1.example.com', socksProxy.config()); const httpResponse = await axios.get('https://api2.example.com', httpProxy.config()); ``` ## šŸ”§ Proxy File Formats The library supports multiple proxy formats: ### URL Format (Recommended) ```txt # HTTP/HTTPS http://192.168.1.1:8080 https://secure-proxy.com:8080 http://username:password@192.168.1.2:8080 # SOCKS5 socks5://192.168.1.10:1080 socks5://username:password@192.168.1.11:1080 # SOCKS4 socks4://192.168.1.12:1080 ``` ### Colon-Separated Format ```txt # Basic format (ip:port) - uses default type from options 192.168.1.1:8080 proxy.example.com:3128 # With protocol (protocol:ip:port) http:192.168.1.1:8080 socks5:192.168.1.10:1080 socks4:192.168.1.11:1080 # With authentication (ip:port:username:password) 192.168.1.2:8080:user123:password123 proxy.example.com:3128:myuser:mypass # With protocol and authentication (protocol:ip:port:username:password) http:192.168.1.3:8080:user:pass socks5:192.168.1.10:1080:user:pass ``` ### Comments and Empty Lines ```txt # This is a comment 192.168.1.1:8080 # Empty lines are ignored socks5://192.168.1.10:1080 # Inline comments are not supported ``` ## šŸ” Protocol Support Details | Protocol | Authentication | URL Format | Colon Format | |----------|---------------|------------|--------------| | HTTP | āœ… Yes | āœ… Yes | āœ… Yes | | HTTPS | āœ… Yes | āœ… Yes | āœ… Yes | | SOCKS5 | āœ… Yes | āœ… Yes | āœ… Yes | | SOCKS4 | āŒ No | āœ… Yes | āœ… Yes | **Note:** SOCKS4 protocol does not support authentication. If you specify credentials with SOCKS4, they will be ignored. ## šŸ“Š Statistics and Monitoring ```javascript const proxy = new ProxyAgent('./proxies.txt'); // Get detailed statistics const stats = proxy.stats(); console.log('Total proxies:', stats.total); console.log('Authenticated:', stats.auth); console.log('Protocol distribution:', stats.protocols); // Output: { http: 5, https: 3, socks5: 8, socks4: 2 } // Monitor current proxy setInterval(() => { const current = proxy.getCurrentProxy(); if (current) { console.log(`Currently using: ${current.protocol}://${current.ip}:${current.port}`); } }, 5000); ``` ## āš™ļø TypeScript Support Full TypeScript definitions are included: ```typescript import ProxyAgent from '@rynn-k/proxy-agent'; const proxy = new ProxyAgent('./proxies.txt', { random: true, type: 'socks5' }); // Type-safe proxy info const info: ProxyAgent.CurrentProxyInfo | null = proxy.getCurrentProxy(); // Type-safe stats const stats: ProxyAgent.ProxyStats = proxy.stats(); ``` ## šŸ› Troubleshooting ### SOCKS proxies not working Make sure the module is properly installed with all dependencies: ```bash npm install @rynn-k/proxy-agent ``` ### Authentication issues with SOCKS4 SOCKS4 does not support authentication. Use SOCKS5 instead: ```txt # Change from socks4://user:pass@192.168.1.1:1080 # To socks5://user:pass@192.168.1.1:1080 ``` ### Mixed protocol errors Ensure each proxy line specifies the correct protocol or set a default type: ```javascript const proxy = new ProxyAgent('./proxies.txt', { type: 'http' // Default for lines without protocol }); ``` ## šŸ“ License MIT