http_mimic 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 +7 -0
- data/CHANGELOG.md +60 -0
- data/LICENSE.txt +21 -0
- data/README.md +263 -0
- data/http_mimic.gemspec +31 -0
- data/lib/http_mimic/client.rb +72 -0
- data/lib/http_mimic/command_builder.rb +333 -0
- data/lib/http_mimic/configuration.rb +41 -0
- data/lib/http_mimic/cookies.rb +111 -0
- data/lib/http_mimic/downloader.rb +272 -0
- data/lib/http_mimic/exceptions.rb +34 -0
- data/lib/http_mimic/headers.rb +101 -0
- data/lib/http_mimic/module_methods.rb +101 -0
- data/lib/http_mimic/request.rb +88 -0
- data/lib/http_mimic/response.rb +99 -0
- data/lib/http_mimic/response_parser.rb +148 -0
- data/lib/http_mimic/version.rb +5 -0
- data/lib/http_mimic.rb +85 -0
- metadata +102 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 32ae2902090ddf216e6f33843f1fb53d82d13cda864a3a71fd7318f5f316cdf4
|
|
4
|
+
data.tar.gz: 907aec51da124505902e104ebf3bce70eb2883490ec8b360f3f0571e6efd98c2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e47bf2078c03dc6a37ecb3478ee5f7a42724375161c63175067fd6df5c8c76fae90b04867eb6f4b8fe03ab2ad2d919ef64dcfd1389ab20befdcb9e2ff245d492
|
|
7
|
+
data.tar.gz: 31c4ebd49e1180914bd949dc23bbc4bd7580dea84f898c7a97bc4977a8501120b1d3d5e6301b65ef2bf7cfa9e5c9bbecd8a7f47806f0a8cf42e1e1b4e7b2e45c
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
## [0.3.0] - 2026-08-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Live Fingerprint Test Suite**: Added integration tests (`rake test:live`) verifying real-world JA3, JA4, and Akamai HTTP/2 fingerprints against live endpoints (`tls.browserleaks.com`, `tls.peet.ws`).
|
|
12
|
+
- **Standard MIT License**: Included official `LICENSE.txt` and repository metadata.
|
|
13
|
+
- **Rakefile Integration**: Added standard Rake test tasks for unit tests, live tests, and full test suites.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **Default Impersonation Target**: Upgraded default impersonation from `chrome116` to modern `chrome131` with Post-Quantum (ML-KEM) and modern Client Hints support.
|
|
17
|
+
- **Internationalization**: Fully translated all code comments, error messages, and documentation into English.
|
|
18
|
+
|
|
19
|
+
## [0.2.0] - 2026-08-24
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- **Webdrivers-like Auto Driver Management (`HttpMimic::Downloader`)**:
|
|
23
|
+
- Automatically downloads and unpacks official binaries from [`lexiforest/curl-impersonate`](https://github.com/lexiforest/curl-impersonate) releases to `~/.http_mimic/bin`.
|
|
24
|
+
- Automatic platform detection for macOS (ARM64 / x86_64), Linux (GNU / MUSL, x86_64, aarch64, arm, i386, riscv64, loongarch64), Windows (x86_64, arm64, i686), and FreeBSD.
|
|
25
|
+
- Manual driver management helpers: `HttpMimic.download_driver!`, `HttpMimic.driver_installed?`, `HttpMimic::Downloader.available_binaries`.
|
|
26
|
+
- Configurable auto-download, target release version, install directory, and custom GitHub repo.
|
|
27
|
+
- **Expanded Browser Target Support**:
|
|
28
|
+
- Support for Chrome (`chrome116`, `chrome120`, `chrome123`, `chrome124`, `chrome131`, `chrome133a`, `chrome136`, `chrome142`, `chrome99-110`).
|
|
29
|
+
- Support for Firefox (`firefox133`, `firefox135`, `firefox144`, `firefox117`, `firefox109`, `firefox102`, `firefox98`).
|
|
30
|
+
- Support for Safari (`safari180`, `safari170`, `safari155`, `safari153`).
|
|
31
|
+
- Support for Edge (`edge101`, `edge99`) and Tor (`tor145`).
|
|
32
|
+
|
|
33
|
+
## [0.1.0] - 2026-08-24
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
- **Initial Release of `HttpMimic`**: A HTTParty-like Ruby client wrapping `curl-impersonate` via `Open3.capture3`.
|
|
37
|
+
- **Core HTTP Verbs**: Support for `get`, `post`, `put`, `patch`, `delete`, `head`, and `options`.
|
|
38
|
+
- **HTTParty-Style API**:
|
|
39
|
+
- Direct module methods: `HttpMimic.get`, `HttpMimic.post`, etc.
|
|
40
|
+
- Class-level DSL mixin via `include HttpMimic` (`base_uri`, `headers`, `default_params`, `default_timeout`, `impersonate`, `proxy`, `cookies`).
|
|
41
|
+
- Reusable instance client: `HttpMimic::Client.new(...)`.
|
|
42
|
+
- **Smart Response & Parser**:
|
|
43
|
+
- Auto-parsing JSON responses and method delegation (`response['key']`, `response.parsed_response`).
|
|
44
|
+
- Case-insensitive header access (`response.headers['content-type']`).
|
|
45
|
+
- Automatic `Set-Cookie` header parsing and cookie jar representation (`response.cookies`).
|
|
46
|
+
- Complete 3xx redirect history tracking (`response.history`).
|
|
47
|
+
- Rich status helpers (`response.success?`, `response.redirect?`, `response.client_error?`, `response.server_error?`, `response.ok?`).
|
|
48
|
+
- **Comprehensive Request Options**:
|
|
49
|
+
- Query parameters (auto URL encoding and nested parameters).
|
|
50
|
+
- Headers, JSON payloads (`json:`), Form URL-encoded data (`body:`), and Multipart (`form:` / `multipart:`).
|
|
51
|
+
- Basic and Digest authentication (`basic_auth:`, `digest_auth:`, `bearer_token:`).
|
|
52
|
+
- Timeouts (`timeout:`, `connect_timeout:`).
|
|
53
|
+
- Proxy and Proxy authentication (`proxy:`, `proxy_auth:`).
|
|
54
|
+
- SSL/TLS settings (`insecure:`, `ssl_ca_file:`, `ssl_cert:`, `ssl_key:`).
|
|
55
|
+
- Raw curl arguments passthrough (`curl_options:`).
|
|
56
|
+
- **Safe CLI Execution**:
|
|
57
|
+
- Uses array arguments in `Open3.capture3` to eliminate shell injection vulnerabilities.
|
|
58
|
+
- Stdin streaming (`stdin_data`) with `-d @-` to bypass OS command line length limits for large payloads.
|
|
59
|
+
- **Unit Test Suite**:
|
|
60
|
+
- Comprehensive tests for header handling, cookie parsing, command generation, response parsing, redirect chains, and platform slug detection.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 anxgang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# HttpMimic
|
|
2
|
+
|
|
3
|
+
`http_mimic` is a Ruby HTTP Client gem built on top of `Open3.capture3` and `curl-impersonate`.
|
|
4
|
+
It provides an elegant, concise, and intuitive **HTTParty-style** API while leveraging [`lexiforest/curl-impersonate`](https://github.com/lexiforest/curl-impersonate) to simulate authentic Chrome, Firefox, Safari, Edge, and Tor TLS / HTTP2 fingerprints (JA3, JA4, Akamai) and handshakes.
|
|
5
|
+
|
|
6
|
+
It also includes **Webdrivers-like automatic driver management**, automatically downloading and managing `curl-impersonate` binaries across macOS, Linux, and Windows without manual setup.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## ๐ Features
|
|
11
|
+
|
|
12
|
+
- **Webdrivers-Style Driver Management**:
|
|
13
|
+
- Automatically downloads and unpacks official binaries from [`lexiforest/curl-impersonate`](https://github.com/lexiforest/curl-impersonate) to `~/.http_mimic/bin`.
|
|
14
|
+
- **Automatic platform & architecture detection** (macOS ARM/Intel, Linux x86_64/aarch64/musl, Windows x86_64/arm64, FreeBSD).
|
|
15
|
+
- Zero configuration requiredโinstalls on first request automatically.
|
|
16
|
+
- Manual driver management helpers: `HttpMimic.download_driver!`, `HttpMimic.driver_installed?`, `HttpMimic::Downloader.available_binaries`.
|
|
17
|
+
- **Authentic Browser Handshakes & Fingerprints**:
|
|
18
|
+
- Chrome support: `chrome131` (default), `chrome124`, `chrome120`, `chrome133a`, `chrome136`, `chrome142`, `chrome99-110`.
|
|
19
|
+
- Firefox support: `firefox135`, `firefox133`, `firefox144`, `firefox117`, `firefox109`, `firefox102`, `firefox98`.
|
|
20
|
+
- Safari support: `safari180`, `safari170`, `safari155`, `safari153`.
|
|
21
|
+
- Edge & Tor support: `edge101`, `edge99`, `tor145`.
|
|
22
|
+
- **HTTParty-Style API**:
|
|
23
|
+
- Direct module methods: `HttpMimic.get`, `HttpMimic.post`, etc.
|
|
24
|
+
- Class mixin via `include HttpMimic` (`base_uri`, `headers`, `default_params`, `default_timeout`, `impersonate`, `proxy`, `cookies`).
|
|
25
|
+
- Reusable instance client: `HttpMimic::Client.new(...)`.
|
|
26
|
+
- **Zero Shell Injection Risk**:
|
|
27
|
+
- Executes commands with array arguments via `Open3.capture3(*cmd_array)`.
|
|
28
|
+
- Uses stdin streaming (`-d @-`) to safely handle large payloads without hitting OS command-line limits.
|
|
29
|
+
- **Smart Response Parsing**:
|
|
30
|
+
- HTTP status helpers: `response.code`, `response.success?`, `response.redirect?`, `response.client_error?`, `response.server_error?`.
|
|
31
|
+
- Case-insensitive header access: `response.headers['Content-Type']`.
|
|
32
|
+
- Automatic `Set-Cookie` header parsing: `response.cookies['session_id']`.
|
|
33
|
+
- Auto-parsed JSON with object delegation: `response['key']`, `response.parsed_response`.
|
|
34
|
+
- Complete 3xx redirect history tracking: `response.history`.
|
|
35
|
+
- **Comprehensive Request Options**:
|
|
36
|
+
- Supports `query`, `headers`, `json`, `body` (form data), `cookies`, `timeout`, `connect_timeout`, `proxy`, `basic_auth`, `digest_auth`, `bearer_token`, `insecure`, custom `curl_options`, and more.
|
|
37
|
+
- **Graceful Fallback**:
|
|
38
|
+
- If a specific binary is unavailable and auto-download is disabled, automatically falls back to system standard `curl`.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## ๐ฆ Installation
|
|
43
|
+
|
|
44
|
+
Add this line to your application's `Gemfile`:
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
gem 'http_mimic'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
And then execute:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
bundle install
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## ๐ค Driver Management
|
|
59
|
+
|
|
60
|
+
`HttpMimic` automatically downloads the corresponding platform binary of `curl-impersonate` on the first request and saves it to `~/.http_mimic/bin`.
|
|
61
|
+
|
|
62
|
+
You can also manage drivers manually:
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
require 'http_mimic'
|
|
66
|
+
|
|
67
|
+
# Check if driver is installed locally
|
|
68
|
+
HttpMimic.driver_installed? # => true / false
|
|
69
|
+
|
|
70
|
+
# Manually trigger download (defaults to latest stable release v2.1.1)
|
|
71
|
+
HttpMimic.download_driver!
|
|
72
|
+
|
|
73
|
+
# Specify a version or force re-download
|
|
74
|
+
HttpMimic.download_driver!(version: 'v2.1.1', force: true)
|
|
75
|
+
|
|
76
|
+
# List all available browser binary names installed locally
|
|
77
|
+
HttpMimic::Downloader.available_binaries
|
|
78
|
+
# => ["curl_chrome131", "curl_chrome120", "curl_firefox135", "curl_safari180", ...]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## ๐ Quick Start
|
|
84
|
+
|
|
85
|
+
### 1. Direct Module Calls
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
require 'http_mimic'
|
|
89
|
+
|
|
90
|
+
# Send a GET request (simulates Chrome 131 fingerprint by default)
|
|
91
|
+
response = HttpMimic.get(
|
|
92
|
+
'https://tls.browserleaks.com/json',
|
|
93
|
+
impersonate: 'chrome131'
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
puts response.code # => 200
|
|
97
|
+
puts response.success? # => true
|
|
98
|
+
puts response['ja3_hash'] # => Authentic Chrome 131 JA3 fingerprint
|
|
99
|
+
puts response.headers['content-type'] # => "application/json"
|
|
100
|
+
|
|
101
|
+
# Send a POST JSON request (simulating Safari 18.0)
|
|
102
|
+
response = HttpMimic.post(
|
|
103
|
+
'https://httpbin.org/post',
|
|
104
|
+
json: { name: 'Alice', role: 'admin' },
|
|
105
|
+
impersonate: 'safari180'
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
puts response.code # => 200
|
|
109
|
+
puts response['json']['name'] # => "Alice"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### 2. Class Mixin Mode (HTTParty Style)
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
class BrowserLeaksClient
|
|
118
|
+
include HttpMimic
|
|
119
|
+
|
|
120
|
+
base_uri 'https://tls.browserleaks.com'
|
|
121
|
+
impersonate 'chrome120' # Default to Chrome 120
|
|
122
|
+
default_timeout 30
|
|
123
|
+
headers 'Accept-Language' => 'en-US,en;q=0.9'
|
|
124
|
+
|
|
125
|
+
def test_fingerprint
|
|
126
|
+
get('/json')
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
client = BrowserLeaksClient.new
|
|
131
|
+
res = client.test_fingerprint
|
|
132
|
+
|
|
133
|
+
puts "HTTP Status: #{res.code}"
|
|
134
|
+
puts "JA3 Hash: #{res['ja3_hash']}"
|
|
135
|
+
puts "User-Agent: #{res['user_agent']}"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
### 3. Instance Mode
|
|
141
|
+
|
|
142
|
+
```ruby
|
|
143
|
+
client = HttpMimic::Client.new(
|
|
144
|
+
base_uri: 'https://api.example.com',
|
|
145
|
+
impersonate: 'firefox135',
|
|
146
|
+
timeout: 15,
|
|
147
|
+
headers: {
|
|
148
|
+
'X-API-KEY' => 'my_api_key'
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Execute GET
|
|
153
|
+
response = client.get('/v1/users', query: { limit: 10 })
|
|
154
|
+
|
|
155
|
+
# Execute POST
|
|
156
|
+
response = client.post('/v1/users', json: { username: 'bob' })
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## โ๏ธ Global Configuration
|
|
162
|
+
|
|
163
|
+
Configure global defaults in an initializer (e.g., `config/initializers/http_mimic.rb`):
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
HttpMimic.configure do |config|
|
|
167
|
+
# Browser simulation & request defaults
|
|
168
|
+
config.default_impersonate = 'chrome131' # Default browser target
|
|
169
|
+
config.default_timeout = 30 # Request timeout (seconds)
|
|
170
|
+
config.default_connect_timeout = 10 # Connection timeout (seconds)
|
|
171
|
+
config.follow_redirects = true # Automatically follow 3xx redirects
|
|
172
|
+
config.max_redirects = 10 # Maximum redirect limit
|
|
173
|
+
config.fallback_to_curl = true # Fall back to system curl if binary is missing
|
|
174
|
+
config.raise_on_error = false # Raise exceptions on HTTP errors / non-zero exits
|
|
175
|
+
config.debug = false # Print debug logs
|
|
176
|
+
|
|
177
|
+
# Webdrivers-like auto-download settings (enabled by default)
|
|
178
|
+
config.auto_download = true # Auto-download missing binary
|
|
179
|
+
config.driver_version = 'v2.1.1' # Target release version
|
|
180
|
+
config.install_dir = File.expand_path('~/.http_mimic/bin') # Directory for binaries
|
|
181
|
+
config.github_repo = 'lexiforest/curl-impersonate' # GitHub source repository
|
|
182
|
+
end
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## ๐ ๏ธ Supported Request Options
|
|
188
|
+
|
|
189
|
+
| Option | Type | Description |
|
|
190
|
+
| :--- | :--- | :--- |
|
|
191
|
+
| `:impersonate` | String | Target browser to mimic (e.g., `'chrome131'`, `'chrome120'`, `'firefox135'`, `'safari180'`, `'tor145'`) |
|
|
192
|
+
| `:binary` | String | Path to a custom `curl-impersonate` executable |
|
|
193
|
+
| `:query` / `:params` | Hash | URL query parameters (supports nested parameters and encoding) |
|
|
194
|
+
| `:headers` | Hash | Custom HTTP request headers |
|
|
195
|
+
| `:json` | Hash / Array | Serialized to JSON with `Content-Type: application/json` |
|
|
196
|
+
| `:body` | Hash / String | Form payload (Hash) or raw request body string |
|
|
197
|
+
| `:cookies` | Hash / String | Request cookies |
|
|
198
|
+
| `:cookie_jar` | String | Path to save cookies (`-c`) |
|
|
199
|
+
| `:cookie_file` | String | Path to read cookies (`-b`) |
|
|
200
|
+
| `:timeout` | Integer / Float | Maximum execution timeout in seconds (`--max-time`) |
|
|
201
|
+
| `:connect_timeout` | Integer / Float | Connection timeout in seconds (`--connect-timeout`) |
|
|
202
|
+
| `:proxy` | String | Proxy address (e.g., `'http://127.0.0.1:8888'`) |
|
|
203
|
+
| `:basic_auth` | Hash | `{ username: 'admin', password: 'secret' }` |
|
|
204
|
+
| `:bearer_token` | String | Appends `Authorization: Bearer <token>` header |
|
|
205
|
+
| `:insecure` | Boolean | Disable SSL certificate verification (`-k`) |
|
|
206
|
+
| `:curl_options` | Array / String | Additional raw curl arguments (e.g., `['--http2', '--compressed']`) |
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## ๐ Response Object
|
|
211
|
+
|
|
212
|
+
The `Response` object wraps the HTTP response with convenient methods:
|
|
213
|
+
|
|
214
|
+
```ruby
|
|
215
|
+
response = HttpMimic.get('https://httpbin.org/get')
|
|
216
|
+
|
|
217
|
+
# Status information
|
|
218
|
+
response.code # => 200 (Integer)
|
|
219
|
+
response.status # => 200
|
|
220
|
+
response.status_message # => "OK"
|
|
221
|
+
response.http_version # => "2"
|
|
222
|
+
response.success? # => true (2xx)
|
|
223
|
+
response.redirect? # => false (3xx)
|
|
224
|
+
response.client_error? # => false (4xx)
|
|
225
|
+
response.server_error? # => false (5xx)
|
|
226
|
+
|
|
227
|
+
# Response body
|
|
228
|
+
response.body # => Raw Body (String)
|
|
229
|
+
response.parsed_response# => Auto-parsed JSON Hash / Array
|
|
230
|
+
response['key'] # => Direct key access to parsed_response
|
|
231
|
+
|
|
232
|
+
# Headers & Cookies
|
|
233
|
+
response.headers['content-type'] # => Case-insensitive header access
|
|
234
|
+
response.cookies['session_id'] # => Parsed Set-Cookie store
|
|
235
|
+
response.history # => Array of redirect history metadata
|
|
236
|
+
|
|
237
|
+
# Underlying execution details
|
|
238
|
+
response.exit_code # => Process exit status (0 for success)
|
|
239
|
+
response.stderr # => Stderr output from curl
|
|
240
|
+
response.command # => Array of the exact CLI arguments executed
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## ๐งช Testing
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# Run offline unit tests
|
|
249
|
+
bundle exec rake test
|
|
250
|
+
|
|
251
|
+
# Run live integration tests against external TLS / JA3 / JA4 / Akamai endpoints
|
|
252
|
+
bundle exec rake test:live
|
|
253
|
+
|
|
254
|
+
# Run all tests
|
|
255
|
+
bundle exec rake test:all
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## ๐ License
|
|
261
|
+
|
|
262
|
+
This project is available as open source under the terms of the [MIT License](file:///Users/ivan/work/Tranyi/_gem/http_mimic/LICENSE.txt).
|
|
263
|
+
Source code is hosted on [GitHub](https://github.com/anxgang/http_mimic).
|
data/http_mimic.gemspec
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require 'http_mimic/version'
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |spec|
|
|
8
|
+
spec.name = "http_mimic"
|
|
9
|
+
spec.version = HttpMimic::VERSION
|
|
10
|
+
spec.authors = ["anxgang"]
|
|
11
|
+
spec.summary = "A HTTParty-like Ruby client wrapping curl-impersonate via Open3."
|
|
12
|
+
spec.description = "Simplifies making HTTP requests using curl-impersonate to mimic real browser TLS/HTTP2 fingerprints."
|
|
13
|
+
spec.homepage = "https://github.com/anxgang/http_mimic"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.metadata = {
|
|
17
|
+
"homepage_uri" => "https://github.com/anxgang/http_mimic",
|
|
18
|
+
"source_code_uri" => "https://github.com/anxgang/http_mimic",
|
|
19
|
+
"bug_tracker_uri" => "https://github.com/anxgang/http_mimic/issues",
|
|
20
|
+
"changelog_uri" => "https://github.com/anxgang/http_mimic/blob/main/CHANGELOG.md"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
spec.required_ruby_version = ">= 2.3.0"
|
|
24
|
+
|
|
25
|
+
spec.files = Dir["lib/**/*.rb", "README.md", "CHANGELOG.md", "LICENSE.txt", "http_mimic.gemspec"]
|
|
26
|
+
spec.require_paths = ["lib"]
|
|
27
|
+
|
|
28
|
+
spec.add_development_dependency "bundler", ">= 1.17"
|
|
29
|
+
spec.add_development_dependency "rake"
|
|
30
|
+
spec.add_development_dependency "minitest"
|
|
31
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HttpMimic
|
|
4
|
+
class Client
|
|
5
|
+
attr_accessor :default_options, :config
|
|
6
|
+
|
|
7
|
+
def initialize(options = {}, config = nil)
|
|
8
|
+
@default_options = options.dup
|
|
9
|
+
@config = config || HttpMimic.configuration.dup
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def get(url, options = {})
|
|
13
|
+
request(:get, url, options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def post(url, options = {})
|
|
17
|
+
request(:post, url, options)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def put(url, options = {})
|
|
21
|
+
request(:put, url, options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def patch(url, options = {})
|
|
25
|
+
request(:patch, url, options)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete(url, options = {})
|
|
29
|
+
request(:delete, url, options)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def head(url, options = {})
|
|
33
|
+
request(:head, url, options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def options(url, options = {})
|
|
37
|
+
request(:options, url, options)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def request(method, url, options = {})
|
|
41
|
+
merged_options = merge_options(@default_options, options)
|
|
42
|
+
Request.new(method, url, merged_options, @config).perform
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def merge_options(base, override)
|
|
48
|
+
result = base.merge(override)
|
|
49
|
+
|
|
50
|
+
# Deep merge headers
|
|
51
|
+
if base[:headers] || override[:headers]
|
|
52
|
+
base_headers = base[:headers] || {}
|
|
53
|
+
over_headers = override[:headers] || {}
|
|
54
|
+
result[:headers] = base_headers.merge(over_headers)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Deep merge query / params
|
|
58
|
+
base_query = base[:query] || base[:params] || {}
|
|
59
|
+
over_query = override[:query] || override[:params] || {}
|
|
60
|
+
if !base_query.empty? || !over_query.empty?
|
|
61
|
+
result[:query] = base_query.merge(over_query)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Deep merge cookies
|
|
65
|
+
if base[:cookies].is_a?(Hash) && override[:cookies].is_a?(Hash)
|
|
66
|
+
result[:cookies] = base[:cookies].merge(override[:cookies])
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
result
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|