Priority: P2
Describe the issue
Rust wreq can attach wreq::tls::TlsInfo to a response when TLS information is enabled on the client. The structure contains the DER-encoded peer certificate and peer certificate chain. wreq-ruby does not expose the builder option or response extension.
This is useful for diagnosing TLS interception, proxy certificate substitution, trust-chain failures, and origin-specific certificate behavior without enabling verbose wire logs. It is also a direct binding feature: unlike DNS/connect/TLS phase timings or a connection_reused? flag, the required data already exists in Rust wreq.
Proposed Ruby API
client = Wreq::Client.new(tls_info: true)
response = client.get("https://example.com")
info = response.tls_info
info.peer_certificate
# => DER-encoded binary String or nil
info.peer_certificate_chain
# => Array of DER-encoded binary Strings, or nil
response.tls_info should return nil when collection was not enabled, the response did not use TLS, or the native transport has no TLS information. When present, return a small immutable Wreq::TlsInfo value object, matching the gem's existing Wreq::TlsError constant style.
Data and ownership semantics
peer_certificate is the DER-encoded leaf certificate as a binary Ruby String (Encoding::BINARY) or nil.
peer_certificate_chain is a frozen Array of binary DER strings or nil. It includes the leaf certificate when Rust wreq supplies it that way.
- Returned data must remain valid independently of response-body consumption and connection-pool reuse.
- Repeated calls may return the same object or equivalent immutable values; object identity is not part of the API.
- Certificate parsing, subject/issuer helpers, fingerprint formatting, and OpenSSL object construction are outside the binding's first scope. Callers can pass DER bytes to
OpenSSL::X509::Certificate when needed.
- Collection stays opt-in because retaining certificate-chain bytes has a cost.
Deliberately out of scope
This issue does not request:
- DNS/connect/TLS/TTFB/download phase timings;
- a connection-reuse flag;
- copies of emitted request headers or browser-profile state;
- client certificates or mTLS configuration; or
- TLS key logging.
Those need separate upstream support, security review, or a concrete use case. Total request duration can already be measured accurately by the Ruby caller with a monotonic clock.
Acceptance criteria
Wreq::Client.new(tls_info: true) enables the existing Rust wreq TLS response extension.
Response#tls_info returns Wreq::TlsInfo for an HTTPS response when native information is available.
Response#tls_info returns nil predictably when disabled or unavailable.
- Leaf and chain values are DER-encoded binary strings with documented ownership and immutability.
- Tests cover enabled, disabled, plain HTTP, leaf certificate, chain, response close/body consumption, and connection reuse.
- No certificate bytes are included automatically in exception messages, logs, or
inspect.
Binding precedent
wreq-python exposes this same Rust feature as opt-in tls_info with peer_certificate, and the underlying Rust TlsInfo also retains the peer certificate chain.
Relevant source
Priority: P2
Describe the issue
Rust wreq can attach
wreq::tls::TlsInfoto a response when TLS information is enabled on the client. The structure contains the DER-encoded peer certificate and peer certificate chain. wreq-ruby does not expose the builder option or response extension.This is useful for diagnosing TLS interception, proxy certificate substitution, trust-chain failures, and origin-specific certificate behavior without enabling verbose wire logs. It is also a direct binding feature: unlike DNS/connect/TLS phase timings or a
connection_reused?flag, the required data already exists in Rust wreq.Proposed Ruby API
response.tls_infoshould returnnilwhen collection was not enabled, the response did not use TLS, or the native transport has no TLS information. When present, return a small immutableWreq::TlsInfovalue object, matching the gem's existingWreq::TlsErrorconstant style.Data and ownership semantics
peer_certificateis the DER-encoded leaf certificate as a binary RubyString(Encoding::BINARY) ornil.peer_certificate_chainis a frozen Array of binary DER strings ornil. It includes the leaf certificate when Rust wreq supplies it that way.OpenSSL::X509::Certificatewhen needed.Deliberately out of scope
This issue does not request:
Those need separate upstream support, security review, or a concrete use case. Total request duration can already be measured accurately by the Ruby caller with a monotonic clock.
Acceptance criteria
Wreq::Client.new(tls_info: true)enables the existing Rust wreq TLS response extension.Response#tls_inforeturnsWreq::TlsInfofor an HTTPS response when native information is available.Response#tls_inforeturnsnilpredictably when disabled or unavailable.inspect.Binding precedent
wreq-pythonexposes this same Rust feature as opt-intls_infowithpeer_certificate, and the underlying RustTlsInfoalso retains the peer certificate chain.Relevant source
src/client.rssrc/client/resp.rs