ruby-proxy-headers 0.2.2 → 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 +4 -4
- data/CHANGELOG.md +49 -0
- data/README.md +48 -1
- data/docs/core-api.md +184 -0
- data/docs/excon.md +29 -0
- data/docs/faraday.md +29 -0
- data/docs/getting-started.md +66 -0
- data/docs/http-gem.md +126 -0
- data/docs/httparty.md +35 -0
- data/docs/index.md +109 -0
- data/docs/net-http.md +29 -0
- data/docs/rest-client.md +96 -0
- data/docs/testing.md +105 -0
- data/docs/typhoeus.md +47 -0
- data/lib/ruby_proxy_headers/connection.rb +1 -8
- data/lib/ruby_proxy_headers/faraday.rb +19 -16
- data/lib/ruby_proxy_headers/http_gem.rb +61 -40
- data/lib/ruby_proxy_headers/net_http.rb +76 -131
- data/lib/ruby_proxy_headers/rest_client.rb +76 -60
- data/lib/ruby_proxy_headers/typhoeus.rb +81 -74
- data/lib/ruby_proxy_headers/version.rb +1 -1
- data/lib/ruby_proxy_headers.rb +45 -0
- metadata +70 -10
- data/DEFERRED.md +0 -29
- data/IMPLEMENTATION_PRIORITY.md +0 -72
- data/LIBRARY_RESEARCH.md +0 -71
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f3b577a3e2e34161a02a0193d153850b0fbadd028a7286c05e23cfdf897e541
|
|
4
|
+
data.tar.gz: cc43f69b2da42d9177df10322db9544e640485d1464a4a2d472f85ce3b0d30d3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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@
|
|
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
|
+
```
|