Send and receive custom proxy headers during HTTPS CONNECT tunneling in modern Ruby HTTP workflows (for example ProxyMesh X-ProxyMesh-IP / X-ProxyMesh-Country).
Most Ruby HTTP clients use Net::HTTP, Faraday, or libcurl without exposing:
- Extra headers on the
CONNECTrequest to the proxy. - Headers from the proxy’s
CONNECTresponse (often discarded after the tunnel is established).
This library adds opt-in support for Net::HTTP, Faraday (2.x via faraday-net_http), HTTParty, and documents Excon’s built-in :ssl_proxy_headers for sends.
- Geo-targeting at tunnel setup: Send country/session directives on
CONNECT. - Sticky-session observability: Read proxy-assigned headers like
X-ProxyMesh-IP. - Works with common Ruby stacks: Useful for scraping and API clients using Net::HTTP-based flows.
gem install ruby-proxy-headersOr add to your Gemfile:
gem 'ruby-proxy-headers'The Net::HTTP patch is pure Ruby. Install faraday, faraday-net_http, httparty, and/or excon when you use those integrations.
require 'uri'
require 'openssl'
require 'ruby_proxy_headers/net_http'
RubyProxyHeaders::NetHTTP.patch!
uri = URI('https://api.ipify.org?format=json')
proxy = URI(ENV.fetch('PROXY_URL'))
http = Net::HTTP.new(uri.host, uri.port, proxy.host, proxy.port, proxy.user, proxy.password)
http.use_ssl = true
# Optional: headers to send on CONNECT (e.g. sticky IP)
http.proxy_connect_request_headers = { 'X-ProxyMesh-IP' => '203.0.113.1' }
res = http.request(Net::HTTP::Get.new(uri))
puts res.body
puts http.last_proxy_connect_response_headers['X-ProxyMesh-IP']Call RubyProxyHeaders::NetHTTP.patch! once before creating connections. You can also read the last CONNECT response headers on the current thread via RubyProxyHeaders.proxy_connect_response_headers.
require 'ruby_proxy_headers/faraday'
conn = RubyProxyHeaders::FaradayIntegration.connection(
proxy: ENV.fetch('PROXY_URL'),
proxy_connect_headers: { 'X-ProxyMesh-Country' => 'US' } # optional
)
res = conn.get('https://api.ipify.org?format=json')
puts res.headers['X-ProxyMesh-IP']Uses the registered adapter :ruby_proxy_headers_net_http, which merges proxy CONNECT response headers into Faraday’s response headers.
require 'httparty'
require 'ruby_proxy_headers/httparty'
RubyProxyHeaders::NetHTTP.patch!
proxy = URI(ENV.fetch('PROXY_URL'))
HTTParty.get(
'https://api.ipify.org?format=json',
http_proxyaddr: proxy.host,
http_proxyport: proxy.port,
http_proxyuser: proxy.user,
http_proxypass: proxy.password,
proxy_connect_request_headers: { 'X-ProxyMesh-IP' => '203.0.113.1' }, # optional
connection_adapter: RubyProxyHeaders::ProxyHeadersConnectionAdapter
)
puts RubyProxyHeaders.proxy_connect_response_headers['X-ProxyMesh-IP']Excon supports sending extra headers on CONNECT with :ssl_proxy_headers. Reading X-ProxyMesh-IP from the CONNECT response is not exposed on the origin response object — see DEFERRED.md.
require 'ruby_proxy_headers/excon'
RubyProxyHeaders::ExconIntegration.get(
'https://api.ipify.org?format=json',
proxy_url: ENV.fetch('PROXY_URL'),
proxy_connect_headers: { 'X-ProxyMesh-Country' => 'US' } # optional
)Same environment variables as python-proxy-headers:
| Variable | Role |
|---|---|
PROXY_URL |
Proxy URL (required for tests) |
TEST_URL |
Target HTTPS URL (default https://api.ipify.org?format=json) |
PROXY_HEADER |
Header to read from CONNECT response (default X-ProxyMesh-IP) |
SEND_PROXY_HEADER |
Optional header name to send on CONNECT |
SEND_PROXY_VALUE |
Optional value for that header |
cd ruby-proxy-headers
bundle install
export PROXY_URL=http://user:pass@proxyhost:port
bundle exec ruby test/test_proxy_headers.rb -v