thinwrap_notifications_transport behaviour (thinwrap_notifications v1.2.0)

View Source

The bring-your-own HTTP seam.

The library never depends on a third-party HTTP client. It defines this one callback and ships thinwrap_notifications_httpc (OTP httpc) as the default. To use hackney, gun, Finch, … implement the behaviour and pass it in the config:

Config = #{provider => sendgrid, api_key => Key,
           transport => {my_hackney_transport, #{pool => mail}}}.

request/2 sends one request and returns one response. Rules:

  • A non-2xx answer is a response, never an error: return {ok, #{status := 429, ...}}. The connector owns status-to-error mapping, so a 429 still reads as rate_limited.
  • Any {error, Reason} (connection refused, DNS, TLS, timeout) is reported as provider_unavailable with no status. Only the kind of the reason (its leading atom, e.g. timeout or failed_connect) is kept: a client's error term may embed the request URL, and for Telegram or a chat webhook the URL path IS the credential.
  • {error, {connector_error, Error}} surfaces a ready-made thinwrap_notifications:connector_error/0 unchanged (the default transport uses it to refuse non-https URLs).
  • Never follow redirects: a 3xx must come back as a response, or the provider's credentials would be re-sent to wherever it points.
  • Header values arrive as UTF-8 binaries whose code points are all ≤ 0xFF (the library rejects anything else first); send them as Latin-1, as httpc does with a character list.

Summary

Types

headers()

-type headers() :: #{binary() => binary()}.

method()

-type method() :: get | post.

request()

-type request() :: #{method := method(), url := binary(), headers := headers(), body => binary()}.

response()

-type response() :: #{status := 100..599, headers := headers(), body := binary()}.

transport()

-type transport() :: {module(), Opts :: term()}.

Callbacks

request(Request, Opts)

-callback request(Request :: request(), Opts :: term()) -> {ok, response()} | {error, term()}.