This document outlines the implementation plan for javascript-proxy-headers.
┌─────────────────────────────────────────────────────────────┐
│ javascript-proxy-headers │
├─────────────────────────────────────────────────────────────┤
│ Library Wrappers (high-level, user-friendly APIs) │
│ ┌─────────┐ ┌───────────┐ ┌─────┐ ┌────────┐ ┌──────────┐ │
│ │ axios │ │node-fetch │ │ got │ │ undici │ │superagent│ │
│ └────┬────┘ └─────┬─────┘ └──┬──┘ └────┬───┘ └────┬─────┘ │
│ │ │ │ │ │ │
│ └────────────┴────┬─────┴─────────┴──────────┘ │
│ │ │
│ ┌──────────────────────▼──────────────────────────────┐ │
│ │ ProxyHeadersAgent (core) │ │
│ │ - Manages CONNECT request with custom headers │ │
│ │ - Captures CONNECT response headers │ │
│ │ - Compatible with http.Agent interface │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Goal: Create ProxyHeadersAgent - the foundation for all library wrappers
Files:
lib/core/proxy-headers-agent.js- Main agent implementationlib/core/connect-parser.js- HTTP CONNECT response parserlib/core/utils.js- Shared utilities
Features:
- Parse proxy URL (host, port, auth)
- Send custom headers in CONNECT request
- Parse CONNECT response headers
- Support Basic auth
- Expose headers via callback or property
- Compatible with Node.js
http.Agentinterface
API:
import { ProxyHeadersAgent } from 'javascript-proxy-headers';
const agent = new ProxyHeadersAgent('http://proxy:8080', {
proxyHeaders: {
'X-ProxyMesh-Country': 'US'
}
});
// After request, headers available on agent
console.log(agent.lastProxyHeaders); // Map of response headersGoal: Native undici support with cleanest API
Files:
lib/undici-proxy.js
Features:
- Custom
ProxyAgentsubclass or wrapper - Support
proxyHeadersoption - Expose CONNECT response headers on response
- Support async header callback
API:
import { request } from 'javascript-proxy-headers/undici';
const { statusCode, headers, body, proxyHeaders } = await request(url, {
proxy: 'http://proxy:8080',
proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});
console.log(proxyHeaders.get('x-proxymesh-ip'));Goal: Drop-in fetch wrapper with proxy header support
Files:
lib/node-fetch-proxy.js
Features:
- Wrapper function around fetch
- Uses ProxyHeadersAgent internally
- Extends Response to include proxyHeaders
API:
import { proxyFetch } from 'javascript-proxy-headers/node-fetch';
const response = await proxyFetch(url, {
proxy: 'http://proxy:8080',
proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});
console.log(response.proxyHeaders.get('x-proxymesh-ip'));Goal: Axios adapter with proxy header support
Files:
lib/axios-proxy.js
Features:
- Custom axios instance factory
- Request interceptor for agent setup
- Response interceptor to merge headers
- Support both sync and async access
API:
import { createProxyAxios } from 'javascript-proxy-headers/axios';
const client = createProxyAxios({
proxy: 'http://proxy:8080',
proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});
const response = await client.get(url);
console.log(response.headers['x-proxymesh-ip']); // Merged into responseGoal: Got instance with proxy header support
Files:
lib/got-proxy.js
Features:
- Use got.extend() for clean integration
- Leverage got's hook system
- Merge proxy headers into response
API:
import { createProxyGot } from 'javascript-proxy-headers/got';
const client = createProxyGot({
proxy: 'http://proxy:8080',
proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});
const response = await client(url);
console.log(response.headers['x-proxymesh-ip']);Goal: SuperAgent plugin for proxy headers
Files:
lib/superagent-proxy.js
Features:
- Plugin function for superagent
- Chainable API
API:
import superagent from 'superagent';
import { proxyPlugin } from 'javascript-proxy-headers/superagent';
const response = await superagent
.get(url)
.use(proxyPlugin({
proxy: 'http://proxy:8080',
proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
}));
console.log(response.headers['x-proxymesh-ip']);The CONNECT response is received before the TLS handshake. Need to:
- Buffer the response
- Parse headers before upgrading to TLS
- Store headers for later retrieval
When using keep-alive/connection pooling:
- Each new CONNECT will have different proxy headers
- Need to track which response corresponds to which request
- Consider disabling pooling for simplicity initially
Proxy headers are available before the target response:
- Option 1: Callback when CONNECT completes
- Option 2: Property on agent, accessed after request
- Option 3: Merge into final response headers
- Provide
.d.tsfiles for all modules - Extend existing library types properly
javascript-proxy-headers/
├── package.json
├── README.md
├── LIBRARY_RESEARCH.md
├── IMPLEMENTATION_PRIORITY.md
├── index.js # Main entry point
├── lib/
│ ├── core/
│ │ ├── proxy-headers-agent.js
│ │ ├── connect-parser.js
│ │ └── utils.js
│ ├── axios-proxy.js
│ ├── node-fetch-proxy.js
│ ├── got-proxy.js
│ ├── undici-proxy.js
│ └── superagent-proxy.js
├── test/
│ ├── run_tests.js
│ ├── core.test.js
│ ├── axios.test.js
│ ├── node-fetch.test.js
│ ├── got.test.js
│ ├── undici.test.js
│ └── superagent.test.js
└── types/
└── index.d.ts
- Core Agent: Can send headers in CONNECT, receive headers from response
- All Libraries: Consistent API pattern across all wrappers
- Tests: Each library tested with real proxy
- Documentation: Clear examples for each library
- TypeScript: Full type definitions
| Risk | Mitigation |
|---|---|
| Node.js internals change | Pin minimum Node version, test across versions |
| Library API changes | Use peer dependencies with version ranges |
| Connection pooling complexity | Start without pooling, add later |
| Performance overhead | Benchmark against direct connections |
Plan created: February 28, 2026