Priority: P1
Describe the issue
wreq-ruby currently converts timeout values to unsigned integer seconds. This prevents callers from setting deadlines below one second and forces them to round values before passing them to the client.
Ruby HTTP libraries normally express timeout durations in seconds while accepting integers and floats. wreq-ruby should follow that convention and retain the caller's precision when converting to Rust's Duration.
Reproduction
Tested with wreq 1.2.4:
require "wreq"
Wreq::Client.new(timeout: 0.25)
# TypeError: invalid type: expected u64, got floating point `0.25`
The same integer-only conversion is used by request-level timeout and read_timeout options. Other duration-valued client controls such as pool_idle_timeout, tcp_keepalive, and tcp_keepalive_interval use the same whole-second conversion.
Proposed Ruby API
Accept non-negative, finite Numeric values in seconds, at minimum Integer and Float:
client = Wreq::Client.new(
timeout: 0.75,
connect_timeout: 0.20,
read_timeout: 0.50
)
client.get("https://example.com", timeout: 0.35)
Integers must remain backward compatible. Internally, fractional values can be converted to a Rust Duration without truncating to whole seconds.
Explicit *_ms options are not necessary for the primary API. Numeric seconds are already the established Ruby convention and allow both concise whole-second values and precise sub-second values.
Validation semantics
- Reject negative values.
- Reject
Float::NAN and positive or negative infinity.
- Reject non-numeric strings instead of coercing them silently.
- Define whether
0 means “expire immediately” or “disable this timeout”; it should not be ambiguous.
- Apply the same duration conversion rules to client-level and request-level timeout options.
- Reuse the conversion contract for every public option documented in seconds; do not leave pool/TCP durations with a separate integer-only rule.
Acceptance criteria
timeout, connect_timeout, and read_timeout accept integer and fractional seconds where each option is supported.
pool_idle_timeout, tcp_keepalive, and tcp_keepalive_interval use the same finite Numeric-seconds conversion.
- A value such as
0.25 is preserved with reasonable Duration precision rather than rounded to 0 or 1.
- Invalid numeric values fail before network I/O and identify the relevant option.
- Existing integer timeout behavior remains compatible.
- Documentation states the unit and semantics of every timeout.
- Tests cover integers, ordinary fractional floats, zero, negative values, NaN, infinity, and request-level overrides.
Ruby ecosystem precedent
Net::HTTP documents Numeric timeout values and accepts floats for open, read, and write timeouts.
- HTTPX timeout options accept fractional seconds and distinguish connection, read, write, request, and operation deadlines.
- http.rb supports fine-grained per-operation timeouts with fractional values.
- Excon documents integer or float timeout seconds.
wreq-python accepts datetime.timedelta for total, connect, read, pool, and TCP timeout options while binding the same Rust Duration-based API.
Relevant wreq-ruby source
Priority: P1
Describe the issue
wreq-ruby currently converts timeout values to unsigned integer seconds. This prevents callers from setting deadlines below one second and forces them to round values before passing them to the client.
Ruby HTTP libraries normally express timeout durations in seconds while accepting integers and floats. wreq-ruby should follow that convention and retain the caller's precision when converting to Rust's
Duration.Reproduction
Tested with wreq 1.2.4:
The same integer-only conversion is used by request-level
timeoutandread_timeoutoptions. Other duration-valued client controls such aspool_idle_timeout,tcp_keepalive, andtcp_keepalive_intervaluse the same whole-second conversion.Proposed Ruby API
Accept non-negative, finite
Numericvalues in seconds, at minimumIntegerandFloat:Integers must remain backward compatible. Internally, fractional values can be converted to a Rust
Durationwithout truncating to whole seconds.Explicit
*_msoptions are not necessary for the primary API.Numericseconds are already the established Ruby convention and allow both concise whole-second values and precise sub-second values.Validation semantics
Float::NANand positive or negative infinity.0means “expire immediately” or “disable this timeout”; it should not be ambiguous.Acceptance criteria
timeout,connect_timeout, andread_timeoutaccept integer and fractional seconds where each option is supported.pool_idle_timeout,tcp_keepalive, andtcp_keepalive_intervaluse the same finite Numeric-seconds conversion.0.25is preserved with reasonableDurationprecision rather than rounded to0or1.Ruby ecosystem precedent
Net::HTTPdocumentsNumerictimeout values and accepts floats for open, read, and write timeouts.wreq-pythonacceptsdatetime.timedeltafor total, connect, read, pool, and TCP timeout options while binding the same RustDuration-based API.Relevant wreq-ruby source
src/client.rssrc/client/req.rslib/wreq_ruby/client.rb