Home

Awesome

katipo

An HTTP/HTTP2 client library for Erlang built around libcurl-multi and libevent.

Status

build status Hex pm Hex Docs

Usage

{ok, _} = application:ensure_all_started(katipo).
Pool = api_server,
{ok, _} = katipo_pool:start(Pool, 2, [{pipelining, multiplex}]).
Url = <<"https://example.com">>.
ReqHeaders = [{<<"User-Agent">>, <<"katipo">>}].
Opts = #{headers => ReqHeaders,
         body => <<"0d5cb3c25b0c5678d5297efa448e1938">>,
         connecttimeout_ms => 5000,
         proxy => <<"http://127.0.0.1:9000">>,
         ssl_verifyhost => false,
         ssl_verifypeer => false},
{ok, #{status := 200,
       headers := RespHeaders,
       cookiejar := CookieJar,
       body := RespBody}} = katipo:post(Pool, Url, Opts).

Or passing the entire request as a map

{ok, _} = application:ensure_all_started(katipo).
Pool = api_server,
{ok, _} = katipo_pool:start(Pool, 2, [{pipelining, multiplex}]).
ReqHeaders = [{<<"User-Agent">>, <<"katipo">>}].
Req = #{url => <<"https://example.com">>.
        method => post,
        headers => ReqHeaders,
        body => <<"0d5cb3c25b0c5678d5297efa448e1938">>,
        connecttimeout_ms => 5000,
        proxy => <<"http://127.0.0.1:9000">>,
        ssl_verifyhost => false,
        ssl_verifypeer => false},
{ok, #{status := 200,
       headers := RespHeaders,
       cookiejar := CookieJar,
       body := RespBody}} = katipo:req(Pool, Req).

Why

We wanted a compatible and high-performance HTTP client so took advantage of the 15+ years of development that has gone into libcurl. To allow large numbers of simultaneous connections libevent is used along with the libcurl-multi interface.

Documentation

API

-type method() :: get | post | put | head | options.
katipo_pool:start(Name :: atom(), size :: pos_integer(), PoolOptions :: proplist()).
katipo_pool:stop(Name :: atom()).

katipo:req(Pool :: atom(), Req :: map()).
katipo:Method(Pool :: atom(), URL :: binary()).
katipo:Method(Pool :: atom(), URL :: binary(), ReqOptions :: map()).

Application Config

OptionValuesDefaultNotes
mod_metrics<code>folsom | exometer | noop</code>noopsee erlang-metrics

Request options

OptionTypeDefaultNotes
headers[{binary(), iodata()}][]
cookiejaropaque (returned in response)[]
bodyiodata()<<>>
connecttimeout_mspos_integer()30000docs
followlocationboolean()falsedocs
ssl_verifyhostboolean()truedocs
ssl_verifypeerboolean()truedocs
capathbinary()undefined
cacertbinary()undefined
timeout_mspos_integer()30000
maxredirsnon_neg_integer()9
proxybinary()undefineddocs
return_metricsboolean()false
tcp_fastopenboolean()falsedocs curl >= 7.49.0
interfacebinary()undefineddocs
unix_socket_pathbinary()undefineddocs curl >= 7.40.0
lock_data_ssl_sessionboolean()falsedocs curl >= 7.23.0
doh_urlbinary()undefineddocs curl >= 7.62.0
http_versioncurl_http_version_none <br> curl_http_version_1_0 <br> curl_http_version_1_1 <br> curl_http_version_2_0 <br> curl_http_version_2tls <br> curl_http_version_2_prior_knowledgecurl_http_version_nonedocs curl >= 7.62.0
sslcertbinary()undefineddocs
sslkeybinary()undefineddocs
sslkey_blobbinary() (DER format)undefineddocs curl >= 7.71.0
keypasswdbinary()undefineddocs
http_authbasic <br> digest <br> ntlm <br> negotiateundefineddocs
userpwdbinary()undefineddocs

Responses

{ok, #{status := pos_integer(),
       headers := headers(),
       cookiejar := cookiejar(),
       body := body(),
       metrics => proplist()}}

{error, #{code := atom(), message := binary()}}

Pool Options

OptionTypeDefaultNote
pipeliningnothing <br> http1 <br> multiplexnothingHTTP pipelining CURLMOPT_PIPELINING
max_pipeline_lengthnon_neg_integer()100
max_total_connectionsnon_neg_integer()0 (no limit)docs

Metrics

System dependencies

Testing

The official Erlang Docker image has everything needed to build and test Katipo

TODO