AudioProxy.S3.HttpClient (audio_proxy v0.4.0)

Copy Markdown View Source

ex_aws's HTTP client behaviour, over OTP's :httpc.

Why we own this

ex_aws ships an adapter for hackney and requires hackney ~> 4.0, but the two do not fit: hackney 4.0 answers a bodyless response — every HEAD, every empty 404 — with a three-element {:ok, status, headers}, and ExAws.Request.Hackney matches only the four-element form. Every head/2 in this proxy would raise CaseClauseError from inside the dependency.

So an adapter had to be written whichever client we picked, and that settled which one: hackney would have brought twelve packages including a QUIC and WebTransport stack for a proxy that makes three kinds of S3 call, while :httpc is OTP's own and already in the release. ex_aws, ex_aws_s3 and sweet_xml are the whole dependency cost.

It is thirty lines against a two-function behaviour, and ex_aws treats the client as pluggable, so swapping back — to a fixed hackney, or to req when the HTTPS source backend wants one anyway — is a config change and this module.

What :httpc needs handling for

Charlists in, binaries out. A request with a body takes its content type as a separate argument rather than a header, and passing it in both places sends it twice. TLS verification is set explicitly because :httpc's defaults have moved across OTP releases, and a client that signs every request and then talks to whoever answers is not worth the signing.

Summary

Functions

Starts the dedicated :httpc profile and sizes its connection pool.

The :ssl options for a request to url.

Functions

setup!(max_sessions)

@spec setup!(pos_integer()) :: :ok

Starts the dedicated :httpc profile and sizes its connection pool.

Called once from AudioProxy.Application.start/2. Idempotent, so a restart of the supervision tree does not fail on an already-started profile.

ssl_options(url)

@spec ssl_options(String.t()) :: keyword()

The :ssl options for a request to url.

Public so a test can assert on the trust store without a TLS handshake.