ruby-proxy-headers 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 227e0393d4ab8a6f03fa72d69541f07a20c73cec9eb3458266dbaa0b74fee36d
4
- data.tar.gz: 299ef710e77b061929ce18159f37e82f002c7a8522b5f0c5ed4319f3d2ab517f
3
+ metadata.gz: 5f3b577a3e2e34161a02a0193d153850b0fbadd028a7286c05e23cfdf897e541
4
+ data.tar.gz: cc43f69b2da42d9177df10322db9544e640485d1464a4a2d472f85ce3b0d30d3
5
5
  SHA512:
6
- metadata.gz: deae95ea2297961bc962a5d9e476ec09b88c85a6a2ac741e1c5d1cb15972f1dc096f2b52e16a70aaca28a77ce04568f00a1109abd2edbdfee45a9727841bff61
7
- data.tar.gz: 55096cb62498dc26f1c1695c8bc46213db91bea6be4c2d056af152cdbbabd07873bc646c2db07a2e36764f8cd8a78188942c77d15b784c3c71acc3e91e2f8a75
6
+ metadata.gz: d6c6c2bcbbccdcf9d731018a3f37aedd15f8c47d0dd49e6f7fb050aadb8d2bce74987ddcc798fbb757f2d6058e1f503f2dc885b69ca9e3ff2eb29951306c7d1a
7
+ data.tar.gz: 1a9a0b38eaadab682f96ed45a850f93f8abd325987687c5ac9d46e21b88ba7980ef7e422f83a29f774a9db7eab41943ffa4e204d323c3333a0ff242453cc589a
data/CHANGELOG.md ADDED
@@ -0,0 +1,49 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.3.0] - 2026-11-12
11
+
12
+ ### Added
13
+
14
+ - `RubyProxyHeaders::Typhoeus` sends proxy headers with libcurl `CURLOPT_PROXYHEADER` (`:proxyheader` and `headeropt: :separate` on Typhoeus 1.7 / Ethon 0.19) and exposes the CONNECT response, including `X-ProxyMesh-IP`, as `proxy_response_headers`.
15
+
16
+ ### Changed
17
+
18
+ - Require Ruby >= 3.2. Dependabot resolves Bundler updates against the gemspec floor, and Ruby 3.1 cannot select nokogiri 1.19 (the release line that installs on the integration job's current Ruby).
19
+ - Development dependencies for the Typhoeus adapter are `typhoeus` `~> 1.7` and `ethon` `>= 0.19.1`, `< 0.20`. The gem still has no runtime dependency on Typhoeus.
20
+ - Gem metadata includes homepage, changelog, and bug tracker URIs. The published gem ships the guides under `docs/` and leaves the internal research notes out.
21
+ - Faraday, HTTParty, Excon, and Net::HTTP guides describe `FaradayIntegration`, `ProxyHeadersConnectionAdapter`, `ExconIntegration`, and `NetHTTP.patch!`.
22
+
23
+ ### Fixed
24
+
25
+ - HTTPS requests through `RubyProxyHeaders::Typhoeus` no longer call `RubyProxyHeaders::NetHTTP.request`, which is not defined.
26
+ - HTTP.rb and RestClient no longer call that missing method. HTTP.rb uses its own `proxy_headers` on CONNECT. RestClient keeps using Net::HTTP, with CONNECT headers attached by the Net::HTTP patch.
27
+ - The Net::HTTP patch no longer replaces `Net::HTTP#connect` with a copy of the Ruby 3.2 method. Socket setup, `timeouted_connect`, and HTTPS proxies stay in the installed net-http.
28
+ - The Faraday adapter no longer overrides faraday-net_http's private `request_with_wrapped_block`. CONNECT response headers are merged from `build_connection` and `call`.
29
+ - `NetHTTP.patch!` still applies after WebMock swaps `Net::HTTP` out and restores it.
30
+
31
+ ## [0.1.0] - 2024-02-28
32
+
33
+ ### Added
34
+
35
+ - Initial release
36
+ - Core `Connection` class for proxy CONNECT handling with custom headers
37
+ - `NetHTTP` module for Net::HTTP integration
38
+ - `Faraday` middleware for Faraday integration
39
+ - `HTTParty` module for HTTParty integration
40
+ - `HTTPGem` module for HTTP.rb integration
41
+ - `Typhoeus` module for Typhoeus integration
42
+ - `Excon` module for Excon integration
43
+ - `RestClient` module for RestClient integration
44
+ - Comprehensive documentation
45
+ - Test suite with RSpec
46
+
47
+ [Unreleased]: https://github.com/proxymesh/ruby-proxy-headers/compare/v0.3.0...HEAD
48
+ [0.3.0]: https://github.com/proxymesh/ruby-proxy-headers/compare/v0.1.0...v0.3.0
49
+ [0.1.0]: https://github.com/proxymesh/ruby-proxy-headers/releases/tag/v0.1.0
data/README.md CHANGED
@@ -94,6 +94,53 @@ HTTParty.get(
94
94
  puts RubyProxyHeaders.proxy_connect_response_headers['X-ProxyMesh-IP']
95
95
  ```
96
96
 
97
+ ## HTTP.rb
98
+
99
+ Requires the `http` gem 6 or newer. Proxy headers are sent on CONNECT by HTTP.rb itself.
100
+
101
+ ```ruby
102
+ require 'ruby_proxy_headers/http_gem'
103
+
104
+ client = RubyProxyHeaders::HTTPGem.create_client(
105
+ proxy: 'http://user:pass@proxy.example.com:31280',
106
+ proxy_headers: { 'X-ProxyMesh-Country' => 'US' }
107
+ )
108
+ response = client.get('https://api.ipify.org?format=json')
109
+ puts response.proxy_response_headers['X-ProxyMesh-IP']
110
+ ```
111
+
112
+ ## RestClient
113
+
114
+ RestClient performs the request. The Net::HTTP patch adds the CONNECT headers.
115
+
116
+ ```ruby
117
+ require 'ruby_proxy_headers/rest_client'
118
+
119
+ response = RubyProxyHeaders::RestClient.get(
120
+ 'https://api.ipify.org?format=json',
121
+ proxy: 'http://user:pass@proxy.example.com:31280',
122
+ proxy_headers: { 'X-ProxyMesh-Country' => 'US' }
123
+ )
124
+ puts response.proxy_response_headers['X-ProxyMesh-IP']
125
+ ```
126
+
127
+ ## Typhoeus
128
+
129
+ Requires Typhoeus 1.7. Proxy headers go to libcurl as `CURLOPT_PROXYHEADER` and are not copied onto the origin request. Header names are documented at <https://docs.proxymesh.com/>.
130
+
131
+ ```ruby
132
+ require 'ruby_proxy_headers/typhoeus'
133
+
134
+ response = RubyProxyHeaders::Typhoeus.get(
135
+ 'https://api.ipify.org?format=json',
136
+ proxy: 'http://user:pass@proxy.example.com:31280',
137
+ proxy_headers: { 'X-ProxyMesh-Country' => 'US' }
138
+ )
139
+ puts response.proxy_response_headers['X-ProxyMesh-IP']
140
+ ```
141
+
142
+ `response.headers` remains the origin response.
143
+
97
144
  ## Excon (send-only; CONNECT response headers)
98
145
 
99
146
  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](DEFERRED.md).
@@ -123,7 +170,7 @@ Same environment variables as [python-proxy-headers](https://github.com/proxymes
123
170
  ```bash
124
171
  cd ruby-proxy-headers
125
172
  bundle install
126
- export PROXY_URL=http://user:pass@proxyhost:port
173
+ export PROXY_URL=http://user:pass@proxy.example.com:31280
127
174
  bundle exec ruby test/test_proxy_headers.rb -v
128
175
  ```
129
176
 
data/docs/core-api.md ADDED
@@ -0,0 +1,184 @@
1
+ # Core API
2
+
3
+ The core API provides low-level access to proxy connection handling. Use this for advanced use cases or when integrating with libraries not directly supported.
4
+
5
+ ## Connection Class
6
+
7
+ The `RubyProxyHeaders::Connection` class handles the HTTPS CONNECT tunnel with custom headers.
8
+
9
+ ### Basic Usage
10
+
11
+ ```ruby
12
+ require 'ruby_proxy_headers'
13
+
14
+ connection = RubyProxyHeaders::Connection.new(
15
+ 'http://user:pass@proxy.example.com:8080',
16
+ proxy_headers: { 'X-ProxyMesh-Country' => 'US' }
17
+ )
18
+
19
+ # Establish tunnel
20
+ ssl_socket = connection.connect('api.ipify.org', 443)
21
+
22
+ # Access proxy response headers
23
+ puts connection.proxy_response_headers
24
+ puts connection.proxy_response_status
25
+
26
+ # Use the socket for your own HTTP implementation
27
+ # ...
28
+
29
+ connection.close
30
+ ```
31
+
32
+ ### Constructor
33
+
34
+ ```ruby
35
+ RubyProxyHeaders::Connection.new(proxy, options = {})
36
+ ```
37
+
38
+ **Parameters:**
39
+
40
+ - `proxy` (String or Hash) - Proxy configuration
41
+ - String: `'http://user:pass@proxy:8080'`
42
+ - Hash: `{ host: 'proxy', port: 8080, user: 'user', password: 'pass' }`
43
+ - `options` (Hash):
44
+ - `:proxy_headers` (Hash) - Headers to send during CONNECT
45
+ - `:connect_timeout` (Integer) - Timeout in seconds (default: 30)
46
+ - `:verify_ssl` (Boolean) - Verify SSL certificates (default: true)
47
+
48
+ ### Instance Methods
49
+
50
+ #### `connect(target_host, target_port = 443)`
51
+
52
+ Establish a tunnel through the proxy to the target.
53
+
54
+ **Returns:** `OpenSSL::SSL::SSLSocket` - TLS-wrapped socket
55
+
56
+ #### `close`
57
+
58
+ Close the connection.
59
+
60
+ ### Instance Attributes
61
+
62
+ - `proxy_response_headers` (Hash) - Headers from proxy CONNECT response
63
+ - `proxy_response_status` (Integer) - HTTP status from CONNECT response
64
+ - `socket` - The underlying socket
65
+
66
+ ## Utility Methods
67
+
68
+ ### `RubyProxyHeaders.parse_proxy_url(url)`
69
+
70
+ Parse a proxy URL into components.
71
+
72
+ ```ruby
73
+ result = RubyProxyHeaders.parse_proxy_url('http://user:pass@proxy:8080')
74
+ # => { host: 'proxy', port: 8080, user: 'user', password: 'pass', scheme: 'http' }
75
+ ```
76
+
77
+ ### `RubyProxyHeaders.build_auth_header(user, password)`
78
+
79
+ Build a Basic authentication header.
80
+
81
+ ```ruby
82
+ auth = RubyProxyHeaders.build_auth_header('user', 'pass')
83
+ # => "Basic dXNlcjpwYXNz"
84
+ ```
85
+
86
+ ## Error Classes
87
+
88
+ ### `RubyProxyHeaders::Error`
89
+
90
+ Base error class.
91
+
92
+ ### `RubyProxyHeaders::ConnectError`
93
+
94
+ Raised when proxy CONNECT fails.
95
+
96
+ ### `RubyProxyHeaders::ProxyAuthenticationError`
97
+
98
+ Raised when proxy returns 407 (authentication required).
99
+
100
+ ## Example: Custom HTTP Implementation
101
+
102
+ ```ruby
103
+ require 'ruby_proxy_headers'
104
+
105
+ connection = RubyProxyHeaders::Connection.new(
106
+ ENV['PROXY_URL'],
107
+ proxy_headers: { 'X-ProxyMesh-Country' => 'US' }
108
+ )
109
+
110
+ begin
111
+ socket = connection.connect('example.com', 443)
112
+
113
+ # Send HTTP request
114
+ socket.write("GET / HTTP/1.1\r\n")
115
+ socket.write("Host: example.com\r\n")
116
+ socket.write("Connection: close\r\n")
117
+ socket.write("\r\n")
118
+
119
+ # Read response
120
+ response = socket.read
121
+ puts response
122
+
123
+ # Access proxy headers
124
+ puts "Proxy IP: #{connection.proxy_response_headers['x-proxymesh-ip']}"
125
+ ensure
126
+ connection.close
127
+ end
128
+ ```
129
+
130
+ ## Example: Integration with Custom Client
131
+
132
+ ```ruby
133
+ require 'ruby_proxy_headers'
134
+
135
+ class CustomHttpClient
136
+ def initialize(proxy_url, proxy_headers = {})
137
+ @proxy_url = proxy_url
138
+ @proxy_headers = proxy_headers
139
+ end
140
+
141
+ def get(url)
142
+ uri = URI.parse(url)
143
+ connection = RubyProxyHeaders::Connection.new(
144
+ @proxy_url,
145
+ proxy_headers: @proxy_headers
146
+ )
147
+
148
+ begin
149
+ socket = connection.connect(uri.host, uri.port || 443)
150
+
151
+ # Build request
152
+ request = "GET #{uri.request_uri} HTTP/1.1\r\n"
153
+ request += "Host: #{uri.host}\r\n"
154
+ request += "Connection: close\r\n"
155
+ request += "\r\n"
156
+
157
+ socket.write(request)
158
+ response = socket.read
159
+
160
+ {
161
+ body: parse_body(response),
162
+ proxy_headers: connection.proxy_response_headers
163
+ }
164
+ ensure
165
+ connection.close
166
+ end
167
+ end
168
+
169
+ private
170
+
171
+ def parse_body(response)
172
+ # Simple body extraction
173
+ response.split("\r\n\r\n", 2).last
174
+ end
175
+ end
176
+
177
+ client = CustomHttpClient.new(
178
+ ENV['PROXY_URL'],
179
+ 'X-ProxyMesh-Country' => 'US'
180
+ )
181
+
182
+ result = client.get('https://api.ipify.org?format=json')
183
+ puts result[:body]
184
+ ```
data/docs/excon.md ADDED
@@ -0,0 +1,29 @@
1
+ # Excon
2
+
3
+ [Excon](https://github.com/excon/excon) already sends extra CONNECT headers as `:ssl_proxy_headers`. `RubyProxyHeaders::ExconIntegration.get` passes them through.
4
+
5
+ Excon does not expose the CONNECT response on the origin response, so `X-ProxyMesh-IP` is not readable from this client. See [DEFERRED.md](../DEFERRED.md).
6
+
7
+ ## Installation
8
+
9
+ ```ruby
10
+ gem 'excon', '~> 1.4'
11
+ gem 'ruby-proxy-headers'
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```ruby
17
+ require 'ruby_proxy_headers/excon'
18
+
19
+ response = RubyProxyHeaders::ExconIntegration.get(
20
+ 'https://api.ipify.org?format=json',
21
+ proxy_url: 'http://user:pass@proxy.example.com:31280',
22
+ proxy_connect_headers: { 'X-ProxyMesh-Country' => 'US' }
23
+ )
24
+
25
+ puts response.status
26
+ puts response.body
27
+ ```
28
+
29
+ Header names are documented at <https://docs.proxymesh.com/>.
data/docs/faraday.md ADDED
@@ -0,0 +1,29 @@
1
+ # Faraday
2
+
3
+ [Faraday](https://lostisland.github.io/faraday/) 2.x with `faraday-net_http` 3.4 or 3.5. `RubyProxyHeaders::FaradayIntegration` builds a connection whose adapter merges CONNECT response headers into `response.headers`.
4
+
5
+ Proxy header names are documented at <https://docs.proxymesh.com/>.
6
+
7
+ ## Installation
8
+
9
+ ```ruby
10
+ gem 'faraday', '~> 2.14'
11
+ gem 'faraday-net_http', '~> 3.4'
12
+ gem 'ruby-proxy-headers'
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```ruby
18
+ require 'ruby_proxy_headers/faraday'
19
+
20
+ conn = RubyProxyHeaders::FaradayIntegration.connection(
21
+ proxy: 'http://user:pass@proxy.example.com:31280',
22
+ proxy_connect_headers: { 'X-ProxyMesh-Country' => 'US' }
23
+ )
24
+
25
+ response = conn.get('https://api.ipify.org?format=json')
26
+ puts response.headers['X-ProxyMesh-IP']
27
+ ```
28
+
29
+ `proxy_connect_headers` are sent only on the CONNECT request. Origin headers are the normal Faraday request headers. When both sides use the same header name, the origin value is kept.
@@ -0,0 +1,66 @@
1
+ # Getting Started
2
+
3
+ ## Installation
4
+
5
+ ```ruby
6
+ gem 'ruby-proxy-headers'
7
+ ```
8
+
9
+ ```bash
10
+ gem install ruby-proxy-headers
11
+ ```
12
+
13
+ Install `faraday` and `faraday-net_http`, `httparty`, `http` (>= 6), `rest-client`, `typhoeus` (~> 1.7), or `excon` only for the client you use.
14
+
15
+ Proxy header names are documented at <https://docs.proxymesh.com/>. Examples below use `http://user:pass@proxy.example.com:31280`.
16
+
17
+ ## Net::HTTP
18
+
19
+ ```ruby
20
+ require 'uri'
21
+ require 'ruby_proxy_headers/net_http'
22
+
23
+ RubyProxyHeaders::NetHTTP.patch!
24
+
25
+ uri = URI('https://api.ipify.org?format=json')
26
+ proxy = URI('http://user:pass@proxy.example.com:31280')
27
+ http = Net::HTTP.new(uri.host, uri.port, proxy.host, proxy.port, proxy.user, proxy.password)
28
+ http.use_ssl = true
29
+ http.proxy_connect_request_headers = { 'X-ProxyMesh-Country' => 'US' }
30
+ response = http.request(Net::HTTP::Get.new(uri))
31
+ puts http.last_proxy_connect_response_headers['X-ProxyMesh-IP']
32
+ ```
33
+
34
+ ## Faraday
35
+
36
+ ```ruby
37
+ require 'ruby_proxy_headers/faraday'
38
+
39
+ conn = RubyProxyHeaders::FaradayIntegration.connection(
40
+ proxy: 'http://user:pass@proxy.example.com:31280',
41
+ proxy_connect_headers: { 'X-ProxyMesh-Country' => 'US' }
42
+ )
43
+ puts conn.get('https://api.ipify.org?format=json').headers['X-ProxyMesh-IP']
44
+ ```
45
+
46
+ ## HTTParty
47
+
48
+ ```ruby
49
+ require 'httparty'
50
+ require 'ruby_proxy_headers/httparty'
51
+
52
+ RubyProxyHeaders::NetHTTP.patch!
53
+ proxy = URI('http://user:pass@proxy.example.com:31280')
54
+ HTTParty.get(
55
+ 'https://api.ipify.org?format=json',
56
+ http_proxyaddr: proxy.host,
57
+ http_proxyport: proxy.port,
58
+ http_proxyuser: proxy.user,
59
+ http_proxypass: proxy.password,
60
+ proxy_connect_request_headers: { 'X-ProxyMesh-Country' => 'US' },
61
+ connection_adapter: RubyProxyHeaders::ProxyHeadersConnectionAdapter
62
+ )
63
+ puts RubyProxyHeaders.proxy_connect_response_headers['X-ProxyMesh-IP']
64
+ ```
65
+
66
+ Per-library pages: [Net::HTTP](net-http.md), [Faraday](faraday.md), [HTTParty](httparty.md), [HTTP.rb](http-gem.md), [Typhoeus](typhoeus.md), [RestClient](rest-client.md), [Excon](excon.md).
data/docs/http-gem.md ADDED
@@ -0,0 +1,126 @@
1
+ # HTTP.rb
2
+
3
+ [HTTP.rb](https://github.com/httprb/http) (the `http` gem) provides a simple Ruby DSL for making HTTP requests. The `RubyProxyHeaders::HTTPGem` module adds proxy header support.
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ gem 'http'
9
+ gem 'ruby-proxy-headers'
10
+ ```
11
+
12
+ ## Basic Usage
13
+
14
+ ### Using Client
15
+
16
+ ```ruby
17
+ require 'ruby_proxy_headers/http_gem'
18
+
19
+ client = RubyProxyHeaders::HTTPGem.create_client(
20
+ proxy: 'http://user:pass@proxy.example.com:31280',
21
+ proxy_headers: { 'X-ProxyMesh-Country' => 'US' }
22
+ )
23
+
24
+ response = client.get('https://api.ipify.org?format=json')
25
+
26
+ puts "Status: #{response.code}"
27
+ puts "Body: #{response.body}"
28
+ puts "Proxy IP: #{client.last_proxy_response_headers['x-proxymesh-ip']}"
29
+ ```
30
+
31
+ ### Standalone Methods
32
+
33
+ ```ruby
34
+ require 'ruby_proxy_headers/http_gem'
35
+
36
+ response = RubyProxyHeaders::HTTPGem.get(
37
+ 'https://api.ipify.org?format=json',
38
+ proxy: 'http://user:pass@proxy.example.com:31280',
39
+ proxy_headers: { 'X-Country' => 'US' }
40
+ )
41
+
42
+ puts response.body
43
+ ```
44
+
45
+ ## API Reference
46
+
47
+ ### `RubyProxyHeaders::HTTPGem.create_client(options)`
48
+
49
+ Create a client with proxy header support.
50
+
51
+ **Parameters:**
52
+
53
+ - `options` (Hash):
54
+ - `:proxy` (String) - Proxy URL (required)
55
+ - `:proxy_headers` (Hash) - Headers to send to proxy
56
+
57
+ **Returns:** `ProxyClient`
58
+
59
+ ### `RubyProxyHeaders::HTTPGem.get(url, options)`
60
+
61
+ Make a GET request.
62
+
63
+ **Parameters:**
64
+
65
+ - `url` (String) - Target URL
66
+ - `options` (Hash) - Same as `create_client`
67
+
68
+ **Returns:** Response object
69
+
70
+ ### `RubyProxyHeaders::HTTPGem.post(url, options)`
71
+
72
+ Make a POST request.
73
+
74
+ **Parameters:**
75
+
76
+ - Same as `get`, plus:
77
+ - `:body` (String) - Request body
78
+
79
+ ## Client Methods
80
+
81
+ The client supports standard HTTP methods:
82
+
83
+ ```ruby
84
+ client = RubyProxyHeaders::HTTPGem.create_client(proxy: '...')
85
+
86
+ client.get(url)
87
+ client.post(url, body: data)
88
+ client.put(url, body: data)
89
+ client.delete(url)
90
+ ```
91
+
92
+ ## Accessing Proxy Headers
93
+
94
+ ```ruby
95
+ client = RubyProxyHeaders::HTTPGem.create_client(
96
+ proxy: 'http://user:pass@proxy.example.com:31280',
97
+ proxy_headers: { 'X-Country' => 'US' }
98
+ )
99
+
100
+ response = client.get('https://example.com')
101
+
102
+ # Access via client
103
+ puts client.last_proxy_response_headers['x-proxymesh-ip']
104
+ ```
105
+
106
+ ## Example: Chained Requests
107
+
108
+ ```ruby
109
+ require 'ruby_proxy_headers/http_gem'
110
+
111
+ client = RubyProxyHeaders::HTTPGem.create_client(
112
+ proxy: ENV['PROXY_URL'],
113
+ proxy_headers: { 'X-ProxyMesh-Session' => 'chain-test' }
114
+ )
115
+
116
+ urls = [
117
+ 'https://api.ipify.org?format=json',
118
+ 'https://httpbin.org/ip',
119
+ 'https://ifconfig.me/ip'
120
+ ]
121
+
122
+ urls.each do |url|
123
+ response = client.get(url)
124
+ puts "#{url}: #{response.body.to_s.strip}"
125
+ end
126
+ ```
data/docs/httparty.md ADDED
@@ -0,0 +1,35 @@
1
+ # HTTParty
2
+
3
+ [HTTParty](https://github.com/jnunemaker/httparty) uses Net::HTTP. Pass `RubyProxyHeaders::ProxyHeadersConnectionAdapter` and call `RubyProxyHeaders::NetHTTP.patch!` once. CONNECT response headers are on the thread afterward, not on the HTTParty response.
4
+
5
+ Proxy header names are documented at <https://docs.proxymesh.com/>.
6
+
7
+ ## Installation
8
+
9
+ ```ruby
10
+ gem 'httparty', '~> 0.24'
11
+ gem 'ruby-proxy-headers'
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```ruby
17
+ require 'httparty'
18
+ require 'ruby_proxy_headers/httparty'
19
+
20
+ RubyProxyHeaders::NetHTTP.patch!
21
+
22
+ proxy = URI('http://user:pass@proxy.example.com:31280')
23
+ response = HTTParty.get(
24
+ 'https://api.ipify.org?format=json',
25
+ http_proxyaddr: proxy.host,
26
+ http_proxyport: proxy.port,
27
+ http_proxyuser: proxy.user,
28
+ http_proxypass: proxy.password,
29
+ proxy_connect_request_headers: { 'X-ProxyMesh-Country' => 'US' },
30
+ connection_adapter: RubyProxyHeaders::ProxyHeadersConnectionAdapter
31
+ )
32
+
33
+ puts response.body
34
+ puts RubyProxyHeaders.proxy_connect_response_headers['X-ProxyMesh-IP']
35
+ ```