Skip to content

proxymesh/ruby-proxy-headers

Repository files navigation

Ruby Proxy Headers

Send and receive custom proxy headers during HTTPS CONNECT tunneling in modern Ruby HTTP workflows (for example ProxyMesh X-ProxyMesh-IP / X-ProxyMesh-Country).

The problem

Most Ruby HTTP clients use Net::HTTP, Faraday, or libcurl without exposing:

  1. Extra headers on the CONNECT request to the proxy.
  2. Headers from the proxy’s CONNECT response (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.

Why teams use this

  • 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.

Installation

gem install ruby-proxy-headers

Or 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.

Net::HTTP

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.

Faraday

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.

HTTParty

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 (send-only; CONNECT response headers)

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
)

Testing (live proxy)

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

Related

About

Send and receive custom proxy headers during HTTPS CONNECT tunneling. Extensions for Faraday, HTTParty, HTTP.rb, Typhoeus, Excon, RestClient.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages