The :httpc adapter for AshHooks.Http — an alternative to the default
AshHooks.Http.Bounded, built on OTP's :httpc, hardened.
IP pinning (closes the DNS-rebinding TOCTOU): the hostname is
resolved ONCE through AshHooks.Ssrf.resolve_public/1 (every answer
must be public), and the connection is made to the VALIDATED address —
not the hostname again. TLS keeps verifying the certificate against the
ORIGINAL hostname (SNI + hostname check), and the host header carries
the original host, so receivers and cert chains are unchanged while the
validate-then-connect gap disappears.
Bounded body (memory DoS floor): the response is read as a STREAM
(:httpc streams only 200/206 — every other status arrives as the
complete result message) and accumulation stops at :max_body_bytes
(default 64 KiB); the remainder is cancelled. Residual, documented: a
hostile NON-2xx giant body is assembled inside :httpc before delivery
(the client's API offers no earlier cut for the transparent path) — the
window is narrowed from every response to error-status responses.
Redirects are DISABLED (autoredirect: false — a 303-on-POST is
otherwise re-issued as GET and the target's body returned). TLS
verifies peers against the OTP CA store, or a pinned private-CA bundle
via the adapter opts ([cacerts: der_list] — same seam as Bounded).
Connect/receive are bounded; the Oban job timeout is the outer bound.
Literal-IP HTTPS fails closed here ({:error, :ip_literal_https_needs_bounded}): this adapter never holds the
socket, so the iPAddress-SAN floor Bounded enforces cannot run, and
chain validation alone would let ANY chain-valid certificate
authenticate the endpoint IP. Use the default adapter for literal-IP
HTTPS endpoints.