Implementation note: IPAddr#to_s string encoding
This note documents why Otto normalizes IP strings produced by its masking
helpers. It is an implementation detail, not a claim about every Ruby 3 release
or every version of the ipaddr default gem.
Verified behavior
Otto's blocking compatibility targets are Ruby 3.2, 3.3, and 3.4. The following behavior was reproduced locally with representative installed patch releases:
| Ruby | ipaddr |
IPv4 IPAddr#to_s |
IPv6 IPAddr#to_s |
|---|---|---|---|
| 3.2.4 | 1.2.5 | US-ASCII |
UTF-8 |
| 3.3.5 | 1.2.7 | US-ASCII |
UTF-8 |
| 3.4.10 | 1.2.7 | US-ASCII |
UTF-8 |
Ruby 4.0.6 with ipaddr 1.2.8 showed the same result, but Ruby 4.0 is a
provisional, non-blocking Otto target. See the
runtime and dependency security policy
for the current support matrix.
You can check the active runtime directly:
require 'ipaddr'
puts RUBY_DESCRIPTION
puts IPAddr::VERSION if defined?(IPAddr::VERSION)
p IPAddr.new('192.168.1.1').to_s.encoding
p IPAddr.new('::1').to_s.encoding
The result comes from the ipaddr implementation's separate IPv4 and IPv6
formatting paths. Treat it as version-specific behavior and rerun the check when
changing Ruby or overriding the default ipaddr gem.
Otto's normalization
An IP address string contains only ASCII bytes, so relabeling a generated
US-ASCII address as UTF-8 does not change its bytes. Otto uses this at the
boundary where IPPrivacy.mask_ip creates IPv4 and IPv6 strings:
IPAddr.new(masked_integer, address_family).to_s.force_encoding(Encoding::UTF_8)
This gives downstream Rack code one encoding for Otto-generated masked
addresses. A US-ASCII string is normally compatible with UTF-8 text; the
encoding difference alone does not imply an error. Normalization prevents code
that requires an explicit UTF-8 label from receiving different labels for IPv4
and IPv6.
Use force_encoding here only because Otto constructed the value from an IP
address and therefore knows every byte is ASCII. Do not apply the same operation
to arbitrary external bytes without validating or transcoding them first.