wreq 1.2.5 → 1.2.7
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/.cargo/config.toml +4 -0
- data/Cargo.lock +135 -119
- data/Cargo.toml +11 -3
- data/Rakefile +6 -0
- data/crates/wreq-util/README.md +1 -1
- data/crates/wreq-util/examples/emulate.rs +3 -3
- data/crates/wreq-util/src/emulate/macros.rs +13 -11
- data/crates/wreq-util/src/emulate/profile/chrome/header.rs +18 -3
- data/crates/wreq-util/src/emulate/profile/firefox/header.rs +16 -0
- data/crates/wreq-util/src/emulate/profile/opera/header.rs +6 -7
- data/crates/wreq-util/tests/client.rs +103 -1
- data/docs/windows-gnu-tokio-crash.md +49 -3
- data/extconf.rb +4 -0
- data/lib/wreq.rb +70 -45
- data/lib/wreq_ruby/body.rb +29 -11
- data/lib/wreq_ruby/client.rb +88 -55
- data/lib/wreq_ruby/cookie.rb +79 -19
- data/lib/wreq_ruby/emulate.rb +74 -6
- data/lib/wreq_ruby/error.rb +5 -7
- data/lib/wreq_ruby/http.rb +74 -0
- data/lib/wreq_ruby/response.rb +3 -0
- data/script/rust_env.rb +85 -0
- data/src/arch.rs +22 -0
- data/src/client/body/form.rs +2 -0
- data/src/client/body/json.rs +47 -14
- data/src/client/body/stream.rs +147 -43
- data/src/client/body.rs +11 -15
- data/src/client/param.rs +7 -7
- data/src/client/req.rs +87 -47
- data/src/client/resp.rs +23 -24
- data/src/client.rs +310 -230
- data/src/cookie.rs +280 -87
- data/src/emulate.rs +85 -50
- data/src/error.rs +198 -41
- data/src/extractor.rs +16 -76
- data/src/header.rs +146 -23
- data/src/http.rs +62 -33
- data/src/lib.rs +26 -20
- data/src/macros.rs +71 -46
- data/src/options.rs +284 -0
- data/src/rt.rs +22 -11
- data/src/serde/de/array_deserializer.rs +48 -0
- data/src/serde/de/array_enumerator.rs +59 -0
- data/src/serde/de/deserializer.rs +307 -0
- data/src/serde/de/enum_deserializer.rs +47 -0
- data/src/serde/de/hash_deserializer.rs +89 -0
- data/src/serde/de/number_deserializer.rs +51 -0
- data/src/serde/de/variant_deserializer.rs +101 -0
- data/src/serde/de.rs +33 -0
- data/src/serde/error.rs +146 -0
- data/src/serde/ser/enums.rs +14 -0
- data/src/serde/ser/map_serializer.rs +56 -0
- data/src/serde/ser/seq_serializer.rs +71 -0
- data/src/serde/ser/serializer.rs +194 -0
- data/src/serde/ser/struct_serializer.rs +106 -0
- data/src/serde/ser/struct_variant_serializer.rs +44 -0
- data/src/serde/ser/tuple_variant_serializer.rs +41 -0
- data/src/serde/ser.rs +18 -0
- data/src/serde/tests.rs +237 -0
- data/src/serde.rs +202 -0
- data/test/body_sender_test.rb +246 -0
- data/test/cookie_test.rb +211 -10
- data/test/json_precision_test.rb +209 -0
- data/test/option_validation_test.rb +311 -0
- data/test/value_semantics_test.rb +238 -0
- data/wreq.gemspec +1 -1
- metadata +28 -4
- data/script/build_windows_gnu.ps1 +0 -264
- data/src/header/helper.rs +0 -112
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
param(
|
|
2
|
-
[switch]$SkipBundleInstall,
|
|
3
|
-
[switch]$SkipToolInstall,
|
|
4
|
-
[switch]$BuildGem,
|
|
5
|
-
[switch]$TestGem,
|
|
6
|
-
[switch]$RunTests,
|
|
7
|
-
[string]$SmokeUrl = $env:WREQ_SMOKE_URL
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
$ErrorActionPreference = "Stop"
|
|
11
|
-
|
|
12
|
-
$target = "x86_64-pc-windows-gnu"
|
|
13
|
-
$platform = "x64-mingw-ucrt"
|
|
14
|
-
$gemPattern = "pkg\wreq-*-$platform.gem"
|
|
15
|
-
if ([string]::IsNullOrWhiteSpace($SmokeUrl)) {
|
|
16
|
-
$SmokeUrl = "https://httpbin.io/get"
|
|
17
|
-
}
|
|
18
|
-
$rubyRoot = Split-Path (Split-Path (Get-Command ruby).Source -Parent) -Parent
|
|
19
|
-
$ucrt = Join-Path $rubyRoot "msys64\ucrt64"
|
|
20
|
-
$ucrtBin = Join-Path $ucrt "bin"
|
|
21
|
-
$msysPackages = @(
|
|
22
|
-
"mingw-w64-ucrt-x86_64-gcc",
|
|
23
|
-
"mingw-w64-ucrt-x86_64-clang",
|
|
24
|
-
"mingw-w64-ucrt-x86_64-cmake",
|
|
25
|
-
"mingw-w64-ucrt-x86_64-pkgconf"
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
function Invoke-Step {
|
|
29
|
-
param(
|
|
30
|
-
[string]$Name,
|
|
31
|
-
[scriptblock]$Command
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
Write-Host "==> $Name"
|
|
35
|
-
& $Command
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function Get-MissingUcrtTools {
|
|
39
|
-
$missing = @()
|
|
40
|
-
|
|
41
|
-
if (-not (Test-Path (Join-Path $ucrtBin "gcc.exe")) -or -not (Test-Path (Join-Path $ucrtBin "g++.exe"))) {
|
|
42
|
-
$missing += "gcc/g++"
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (-not (Test-Path (Join-Path $ucrtBin "clang.exe")) -or -not (Test-Path (Join-Path $ucrtBin "libclang.dll"))) {
|
|
46
|
-
$missing += "clang/libclang"
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (-not (Test-Path (Join-Path $ucrtBin "cmake.exe"))) {
|
|
50
|
-
$missing += "cmake"
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (-not (Test-Path (Join-Path $ucrtBin "pkgconf.exe")) -and -not (Test-Path (Join-Path $ucrtBin "pkg-config.exe"))) {
|
|
54
|
-
$missing += "pkgconf"
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
$missing
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function Get-LatestPlatformGem {
|
|
61
|
-
$gem = Get-ChildItem -Path $gemPattern -ErrorAction SilentlyContinue |
|
|
62
|
-
Sort-Object LastWriteTime -Descending |
|
|
63
|
-
Select-Object -First 1
|
|
64
|
-
|
|
65
|
-
if (-not $gem) {
|
|
66
|
-
throw "No Windows GNU platform gem found at '$gemPattern'. Re-run with -BuildGem first."
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
$gem
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function Invoke-RubySmoke {
|
|
73
|
-
param(
|
|
74
|
-
[string]$Name,
|
|
75
|
-
[string]$Code
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
Write-Host "Smoke: $Name"
|
|
79
|
-
ruby -e $Code
|
|
80
|
-
if ($LASTEXITCODE -ne 0) {
|
|
81
|
-
throw "$Name failed with exit code $LASTEXITCODE."
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
Invoke-Step "Check Ruby platform" {
|
|
86
|
-
$rubyArch = & ruby -rrbconfig -e "print RbConfig::CONFIG['arch']"
|
|
87
|
-
if ($rubyArch -ne $platform) {
|
|
88
|
-
throw "Expected Ruby platform '$platform', got '$rubyArch'. Use RubyInstaller UCRT for this build."
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
ruby -v
|
|
92
|
-
ruby -rrbconfig -rrubygems -e "puts RbConfig::CONFIG.values_at('arch', 'host', 'CC').join(%q{ }); puts Gem::Platform.local"
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
Invoke-Step "Install Rust target" {
|
|
96
|
-
$installedTargets = @(rustup target list --installed)
|
|
97
|
-
if ($installedTargets -contains $target) {
|
|
98
|
-
Write-Host "Rust target $target already installed; skipping rustup."
|
|
99
|
-
return
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
rustup target add $target
|
|
103
|
-
if ($LASTEXITCODE -ne 0) {
|
|
104
|
-
throw "Failed to install Rust target $target."
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
Invoke-Step "Check MSYS2 UCRT build tools" {
|
|
109
|
-
$missing = @(Get-MissingUcrtTools)
|
|
110
|
-
if ($missing.Count -eq 0) {
|
|
111
|
-
Write-Host "MSYS2 UCRT build tools already present; skipping pacman."
|
|
112
|
-
return
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if ($SkipToolInstall) {
|
|
116
|
-
throw "Missing MSYS2 UCRT build tools: $($missing -join ', '). Re-run without -SkipToolInstall or install them with ridk."
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
Write-Host "Missing MSYS2 UCRT build tools: $($missing -join ', ')"
|
|
120
|
-
ridk exec pacman -S --needed --noconfirm @msysPackages
|
|
121
|
-
if ($LASTEXITCODE -ne 0) {
|
|
122
|
-
$stillMissing = @(Get-MissingUcrtTools)
|
|
123
|
-
if ($stillMissing.Count -eq 0) {
|
|
124
|
-
Write-Warning "pacman returned exit code $LASTEXITCODE, but all required tools are present; continuing."
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
throw "Failed to install MSYS2 UCRT build tools. Missing: $($stillMissing -join ', '). If pacman cannot lock its database, close other pacman/ridk shells, run PowerShell as Administrator, or install RubyInstaller in a user-writable directory."
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
Invoke-Step "Configure Windows GNU toolchain" {
|
|
133
|
-
$env:CARGO_BUILD_TARGET = $target
|
|
134
|
-
$env:LIBCLANG_PATH = $ucrtBin
|
|
135
|
-
$env:CC_x86_64_pc_windows_gnu = Join-Path $ucrtBin "gcc.exe"
|
|
136
|
-
$env:CXX_x86_64_pc_windows_gnu = Join-Path $ucrtBin "g++.exe"
|
|
137
|
-
$env:CMAKE = Join-Path $ucrtBin "cmake.exe"
|
|
138
|
-
Remove-Item Env:\CMAKE_GENERATOR -ErrorAction SilentlyContinue
|
|
139
|
-
|
|
140
|
-
rustc -Vv
|
|
141
|
-
Write-Host "LIBCLANG_PATH=$env:LIBCLANG_PATH"
|
|
142
|
-
Write-Host "CC_x86_64_pc_windows_gnu=$env:CC_x86_64_pc_windows_gnu"
|
|
143
|
-
Write-Host "CXX_x86_64_pc_windows_gnu=$env:CXX_x86_64_pc_windows_gnu"
|
|
144
|
-
Write-Host "CMAKE=$env:CMAKE"
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (-not $SkipBundleInstall) {
|
|
148
|
-
Invoke-Step "Install Ruby dependencies" {
|
|
149
|
-
bundle install
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
Invoke-Step "Compile native extension" {
|
|
154
|
-
ridk exec ruby -S bundle exec rake compile
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
Invoke-Step "Sync versioned extension" {
|
|
158
|
-
$rubyMinor = & ruby -e "print RUBY_VERSION[/\A\d+\.\d+/]"
|
|
159
|
-
$dest = "lib\wreq_ruby\$rubyMinor"
|
|
160
|
-
New-Item -ItemType Directory -Force $dest | Out-Null
|
|
161
|
-
Copy-Item "lib\wreq_ruby\wreq_ruby.so" (Join-Path $dest "wreq_ruby.so") -Force
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
Invoke-Step "Verify extension loads" {
|
|
165
|
-
ruby -Ilib -rwreq -e "puts Wreq::VERSION; puts Wreq::Client.new.class"
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if ($RunTests) {
|
|
169
|
-
Invoke-Step "Run tests" {
|
|
170
|
-
ridk exec ruby -S bundle exec rake test
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if ($BuildGem) {
|
|
175
|
-
Invoke-Step "Build local platform gem" {
|
|
176
|
-
$rubyMinor = & ruby -e "print RUBY_VERSION[/\A\d+\.\d+/]"
|
|
177
|
-
$dest = "lib\wreq_ruby\$rubyMinor"
|
|
178
|
-
New-Item -ItemType Directory -Force $dest | Out-Null
|
|
179
|
-
Copy-Item "lib\wreq_ruby\wreq_ruby.so" (Join-Path $dest "wreq_ruby.so") -Force
|
|
180
|
-
|
|
181
|
-
ruby script/build_platform_gem.rb $platform
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if ($TestGem) {
|
|
186
|
-
Invoke-Step "Install and smoke test platform gem" {
|
|
187
|
-
$gem = Get-LatestPlatformGem
|
|
188
|
-
$gemHome = Join-Path ([System.IO.Path]::GetTempPath()) "wreq-gem-test-$PID"
|
|
189
|
-
$gemBin = Join-Path $gemHome "bin"
|
|
190
|
-
$testDir = Join-Path ([System.IO.Path]::GetTempPath()) "wreq-gem-test-cwd-$PID"
|
|
191
|
-
|
|
192
|
-
Remove-Item -Recurse -Force $gemHome, $testDir -ErrorAction SilentlyContinue
|
|
193
|
-
New-Item -ItemType Directory -Force $gemHome, $gemBin, $testDir | Out-Null
|
|
194
|
-
|
|
195
|
-
$oldGemHome = $env:GEM_HOME
|
|
196
|
-
$oldGemPath = $env:GEM_PATH
|
|
197
|
-
$oldGemrc = $env:GEMRC
|
|
198
|
-
$oldRubyopt = $env:RUBYOPT
|
|
199
|
-
$oldRubylib = $env:RUBYLIB
|
|
200
|
-
$oldBundleGemfile = $env:BUNDLE_GEMFILE
|
|
201
|
-
$oldBundleBinPath = $env:BUNDLE_BIN_PATH
|
|
202
|
-
$oldBundlerVersion = $env:BUNDLER_VERSION
|
|
203
|
-
$oldSmokeUrl = $env:WREQ_SMOKE_URL
|
|
204
|
-
$oldWreqGemHome = $env:WREQ_GEM_HOME
|
|
205
|
-
|
|
206
|
-
try {
|
|
207
|
-
$env:GEM_HOME = $gemHome
|
|
208
|
-
$env:GEM_PATH = $gemHome
|
|
209
|
-
$env:GEMRC = ""
|
|
210
|
-
$env:RUBYOPT = ""
|
|
211
|
-
$env:RUBYLIB = ""
|
|
212
|
-
$env:BUNDLE_GEMFILE = ""
|
|
213
|
-
$env:BUNDLE_BIN_PATH = ""
|
|
214
|
-
$env:BUNDLER_VERSION = ""
|
|
215
|
-
$env:WREQ_SMOKE_URL = $SmokeUrl
|
|
216
|
-
$env:WREQ_GEM_HOME = $gemHome
|
|
217
|
-
|
|
218
|
-
gem install --norc --local --install-dir $gemHome --bindir $gemBin --no-document --force --no-user-install $gem.FullName
|
|
219
|
-
if ($LASTEXITCODE -ne 0) {
|
|
220
|
-
throw "Failed to install $($gem.FullName)."
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
Push-Location $testDir
|
|
224
|
-
try {
|
|
225
|
-
Invoke-RubySmoke "Load installed platform gem" @'
|
|
226
|
-
STDOUT.sync = true
|
|
227
|
-
STDERR.sync = true
|
|
228
|
-
require "wreq"
|
|
229
|
-
spec = Gem.loaded_specs.fetch("wreq")
|
|
230
|
-
expected = File.expand_path(ENV.fetch("WREQ_GEM_HOME"))
|
|
231
|
-
actual = File.expand_path(spec.full_gem_path)
|
|
232
|
-
raise "loaded #{actual}, expected under #{expected}" unless actual.start_with?(expected)
|
|
233
|
-
puts "loaded #{spec.full_name}"
|
|
234
|
-
puts actual
|
|
235
|
-
puts "wreq #{Wreq::VERSION}"
|
|
236
|
-
'@
|
|
237
|
-
|
|
238
|
-
Invoke-RubySmoke "Request through installed platform gem" @'
|
|
239
|
-
STDOUT.sync = true
|
|
240
|
-
STDERR.sync = true
|
|
241
|
-
require "wreq"
|
|
242
|
-
client = Wreq::Client.new
|
|
243
|
-
resp = client.get(ENV.fetch("WREQ_SMOKE_URL"), timeout: 20)
|
|
244
|
-
puts "HTTP #{resp.code}"
|
|
245
|
-
raise "unexpected status #{resp.code}" unless resp.code == 200
|
|
246
|
-
'@
|
|
247
|
-
} finally {
|
|
248
|
-
Pop-Location
|
|
249
|
-
}
|
|
250
|
-
} finally {
|
|
251
|
-
$env:GEM_HOME = $oldGemHome
|
|
252
|
-
$env:GEM_PATH = $oldGemPath
|
|
253
|
-
$env:GEMRC = $oldGemrc
|
|
254
|
-
$env:RUBYOPT = $oldRubyopt
|
|
255
|
-
$env:RUBYLIB = $oldRubylib
|
|
256
|
-
$env:BUNDLE_GEMFILE = $oldBundleGemfile
|
|
257
|
-
$env:BUNDLE_BIN_PATH = $oldBundleBinPath
|
|
258
|
-
$env:BUNDLER_VERSION = $oldBundlerVersion
|
|
259
|
-
$env:WREQ_SMOKE_URL = $oldSmokeUrl
|
|
260
|
-
$env:WREQ_GEM_HOME = $oldWreqGemHome
|
|
261
|
-
Remove-Item -Recurse -Force $gemHome, $testDir -ErrorAction SilentlyContinue
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
data/src/header/helper.rs
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
//! Ruby value conversion helpers for `Wreq::Headers`.
|
|
2
|
-
|
|
3
|
-
use bytes::Bytes;
|
|
4
|
-
use http::{HeaderName, HeaderValue};
|
|
5
|
-
use magnus::{Error, RArray, RString, Symbol, TryConvert, Value, prelude::*, typed_data::Obj};
|
|
6
|
-
|
|
7
|
-
use crate::error::{
|
|
8
|
-
header_name_error_to_magnus, header_value_error_to_magnus, type_value_error_to_magnus,
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
use super::Headers;
|
|
12
|
-
|
|
13
|
-
/// Maximum number of field-value occurrences supported by `HeaderMap`.
|
|
14
|
-
const MAX_HEADER_ENTRIES: usize = 1 << 15;
|
|
15
|
-
|
|
16
|
-
/// Build a header collection from a Ruby source object.
|
|
17
|
-
///
|
|
18
|
-
/// Accepts another `Wreq::Headers`, a Hash, or any object whose `to_a` result
|
|
19
|
-
/// contains two-element name-value pairs. Array values are delegated to
|
|
20
|
-
/// [`Headers::append`] so each value remains a separate occurrence.
|
|
21
|
-
pub(super) fn from_source(source: Value) -> Result<Headers, Error> {
|
|
22
|
-
if let Ok(headers) = Obj::<Headers>::try_convert(source) {
|
|
23
|
-
return Ok((*headers).clone());
|
|
24
|
-
}
|
|
25
|
-
if !source.respond_to("to_a", false)? {
|
|
26
|
-
return Err(type_value_error_to_magnus(
|
|
27
|
-
"Expected Headers, a Hash, or an enumerable of pairs",
|
|
28
|
-
));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let pairs: RArray = source.funcall_public("to_a", ())?;
|
|
32
|
-
let headers = Headers::default();
|
|
33
|
-
for pair in pairs {
|
|
34
|
-
let pair = RArray::try_convert(pair)
|
|
35
|
-
.map_err(|_| type_value_error_to_magnus("Expected each header entry to be a pair"))?;
|
|
36
|
-
if pair.len() != 2 {
|
|
37
|
-
return Err(type_value_error_to_magnus(
|
|
38
|
-
"Expected each header entry to contain a name and value",
|
|
39
|
-
));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
headers.append(pair.entry(0)?, pair.entry(1)?)?;
|
|
43
|
-
}
|
|
44
|
-
Ok(headers)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/// Convert a Ruby String or Symbol into a normalized HTTP header name.
|
|
48
|
-
///
|
|
49
|
-
/// Symbol underscores are changed to hyphens before [`HeaderName`] validates
|
|
50
|
-
/// and normalizes the name. Other Ruby types produce `Wreq::BuilderError`.
|
|
51
|
-
pub(super) fn parse_header_name(value: Value) -> Result<HeaderName, Error> {
|
|
52
|
-
let name = match (RString::from_value(value), Symbol::from_value(value)) {
|
|
53
|
-
(Some(name), _) => name.to_bytes(),
|
|
54
|
-
(None, Some(name)) => Bytes::from(name.name()?.replace('_', "-")),
|
|
55
|
-
(None, None) => {
|
|
56
|
-
return Err(type_value_error_to_magnus(
|
|
57
|
-
"Expected a String or Symbol header name",
|
|
58
|
-
));
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
HeaderName::from_bytes(name.as_ref()).map_err(header_name_error_to_magnus)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/// Convert a Ruby String or Array of Strings into validated header values.
|
|
65
|
-
///
|
|
66
|
-
/// Each Array element becomes one [`HeaderValue`]. An empty Array therefore
|
|
67
|
-
/// produces no values, allowing `set` to remove a header and `append` to do
|
|
68
|
-
/// nothing.
|
|
69
|
-
pub(super) fn parse_header_values(value: Value) -> Result<Vec<HeaderValue>, Error> {
|
|
70
|
-
if let Some(values) = RArray::from_value(value) {
|
|
71
|
-
values.into_iter().map(parse_header_value).collect()
|
|
72
|
-
} else {
|
|
73
|
-
Ok(vec![parse_header_value(value)?])
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/// Convert one Ruby String into a validated HTTP header value.
|
|
78
|
-
///
|
|
79
|
-
/// Invalid Ruby types and bytes rejected by [`HeaderValue`] are mapped to
|
|
80
|
-
/// `Wreq::BuilderError`.
|
|
81
|
-
fn parse_header_value(value: Value) -> Result<HeaderValue, Error> {
|
|
82
|
-
let value = RString::try_convert(value)
|
|
83
|
-
.map_err(|_| type_value_error_to_magnus("Expected a String header value"))?;
|
|
84
|
-
HeaderValue::from_maybe_shared(value.to_bytes()).map_err(header_value_error_to_magnus)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/// Validate the resulting number of header occurrences before a mutation.
|
|
88
|
-
///
|
|
89
|
-
/// `current` is the collection length, `replaced` is the number of existing
|
|
90
|
-
/// occurrences removed by `set`, and `added` is the incoming value count.
|
|
91
|
-
/// Checked arithmetic prevents overflow; an invalid calculation or a result
|
|
92
|
-
/// above the native [`HeaderMap`](http::HeaderMap) limit returns
|
|
93
|
-
/// `Wreq::BuilderError` without mutating the collection.
|
|
94
|
-
pub(super) fn ensure_header_count(
|
|
95
|
-
current: usize,
|
|
96
|
-
replaced: usize,
|
|
97
|
-
added: usize,
|
|
98
|
-
) -> Result<(), Error> {
|
|
99
|
-
let count = current
|
|
100
|
-
.checked_sub(replaced)
|
|
101
|
-
.and_then(|count| count.checked_add(added));
|
|
102
|
-
if count.is_some_and(|count| count <= MAX_HEADER_ENTRIES) {
|
|
103
|
-
Ok(())
|
|
104
|
-
} else {
|
|
105
|
-
Err(header_count_error())
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/// Build the error returned when the native header map reaches its entry limit.
|
|
110
|
-
pub(super) fn header_count_error() -> Error {
|
|
111
|
-
type_value_error_to_magnus("Header collection exceeds 32,768 entries")
|
|
112
|
-
}
|