Production-oriented split proxy for constrained networks.
- Client proxy listens on port 8080 and accepts browser traffic.
- Backend proxy listens on port 9000, fetches origin content, optimizes/compresses HTTP responses, and tunnels HTTPS via CONNECT.
- HTTPS is tunneled end-to-end (no MITM/decryption).
npm install
# terminal 1
npm run backend
# terminal 2
npm run clientBrowser proxy settings:
- HTTP proxy: 127.0.0.1:8080
- HTTPS proxy: 127.0.0.1:8080
The runtime now uses configurable production-safe values.
HTTP_REQUEST_TIMEOUT_MS(backend HTTP origin request timeout, default60000)BACKEND_REQUEST_TIMEOUT_MS(client->backend HTTP timeout, default60000)CONNECT_IDLE_TIMEOUT_MS(backend CONNECT tunnel idle timeout, default600000)CONNECT_HANDSHAKE_TIMEOUT_MS(client CONNECT handshake timeout, default60000)SHUTDOWN_GRACE_MS(grace period before forced close on SIGINT/SIGTERM, default5000)
Both servers now perform idempotent graceful shutdown and force-close lingering sockets after the grace period.
backend-server.jsbackend proxy serverclient-proxy.jsclient-side proxy servermiddleware/optimization/caching/compression pipelinetests/all test scriptsutils/utility helpers
node tests/test-both-fixes.jsExpected:
- HTTP response includes
content-encoding: gzip - CONNECT returns
200 Connection Established-days 365 -sha256
Whitelist specific domains for optimization:
// config.js
filtering: {
domainWhitelist: ['example.com', 'news.com'], // Only optimize these
domainBlacklist: ['cdn.example.com'] // Skip these
}For faster compression (lower latency) on relay node, reduce Brotli quality:
// config.js
compression: {
brotli: { quality: 8 } // 1-11, lower = faster but larger
}// Clear all cache on startup or periodically
// In proxy-server.js
const { clearAllCache } = require('./middleware/cache');
clearAllCache();-
Verify CA certificate installed on device:
- Android: Settings -> Security -> Certificate Management (should show "2G Website Compressor")
- iOS: Settings -> General -> About -> Certificate Trust Settings (enable certificate)
-
Check proxy is accessible:
curl -x http://localhost:8888 https://example.com
-
Check firewall allows traffic on port 8888:
sudo ufw allow 8888 # Linux
-
Temporarily disable optimization for specific domain in
config.js:filtering: { domainBlacklist: ['problematic-site.com'] }
-
Enable debug logging to identify which middleware fails:
DEBUG=true npm start
-
Report issue with domain name (may need to adjust HTML/JS minification)
If 2G device is heavily CPU-constrained:
- Reduce Brotli quality (faster compression):
brotli: { quality: 6 } // Faster, slightly less compression
- Disable image optimization (most CPU-intensive):
image: { enabled: false }
Edit cache size limit:
cache: {
maxSize: 50 // Reduced from 100 MB
}Or manually clear:
rm -rf ./cache/*| Site | Original | Compressed | Reduction | 2G Time Saved |
|---|---|---|---|---|
| News homepage | 2.5 MB | 320 KB | 87% | ~120 sec |
| E-commerce product | 1.8 MB | 210 KB | 88% | ~90 sec |
| Blog post | 450 KB | 42 KB | 91% | ~30 sec |
| Social media feed | 3.2 MB | 280 KB | 91% | ~140 sec |
2G Network Assumptions: 115 Kbps, 400ms latency
- Bandwidth: ~1 Mbps (handles proxying, not optimization overhead)
- CPU: 1 core (Node.js lightweight, minimal per-request optimization)
- Memory: 512 MB (cache + connections)
- Storage: 100+ MB (response caching)
Areas for contribution:
- HTTP/2 multiplexing support (faster sequential asset loading)
- WebSocket delta-sync (reload only changed content)
- Progressive image loading (placeholder -> preview -> full)
- Video transcoding (HLS to minimal bitrate)
- Distributed proxy (load balancing across relay nodes)
- Better Socks proxy support
MIT
- Opera Mini Architecture Paper
- Google's Mobile Optimization Guide
- Brotli Compression Algorithm
- WebP Image Format
- 2G Network Performance
For issues, feature requests, or questions:
- Check troubleshooting section above
- Enable debug logging to diagnose issues
- Test with unit tests to verify middleware components
- Check config.js for optimization toggles