katipo
=====
[![Build Status][travis_ci_image]][travis_ci]
An HTTP library for Erlang built around libcurl-multi and libevent.
### Status
Beta `0.2.2`
[Hex.pm package](https://hex.pm/packages/katipo)
### Usage
```erlang
{ok, _} = application:ensure_all_started(katipo).
Url = <<"https://example.com">>.
ReqHeaders = [{<<"User-Agent">>, <<"katipo">>}].
Opts = #{headers => ReqHeaders,
body => <<"0d5cb3c25b0c5678d5297efa448e1938">>,
connecttimeout_ms => 5000,
proxy => <<"http://127.0.0.1:9000">>,
sslverifyhost => false,
sslverifypeer => false},
{ok, #{status := 200,
headers := RespHeaders,
cookiejar := CookieJar,
body := RespBody}} = katipo:post(Url, Opts).
```
Or passing the entire request as a map
```erlang
{ok, _} = application:ensure_all_started(katipo).
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">>,
sslverifyhost => false,
sslverifypeer => false},
{ok, #{status := 200,
headers := RespHeaders,
cookiejar := CookieJar,
body := RespBody}} = katipo:req(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
```erlang
-type method() :: get | post | put | head | options.
katipo:req(Req :: map()).
katipo:Method(URL :: binary()).
katipo:Method(URL :: binary(), Options :: map()).
```
#### Request options
| Option | Type | Default |
|:--------------------|:------------------------------- |:----------------- |
| `headers` | `[{binary(), iodata()}]` | `[]` |
| `cookiejar` | opaque (returned in response) | `[]` |
| `body` | `iodata()` | `<<>>` |
| `connecttimeout_ms` | `pos_integer()` | 30000 |
| `followlocation` | `boolean()` | `false` |
| `ssl_verifyhost` | `boolean()` | `true` |
| `ssl_verifypeer` | `boolean()` | `true` |
| `capath` | `binary()` | `undefined` |
| `timeout_ms` | `pos_integer()` | 30000 |
| `maxredirs` | `non_neg_integer()` | 9 |
| `proxy` | `binary()` | `undefined` |
#### Responses
```erlang
{ok, #{status => pos_integer(),
headers => headers(),
cookiejar => cookiejar(),
body => body()}}
{error, #{code => atom(), message => binary()}}
```
#### Application config
| Option | Type | Default | Note |
|:----------------------|:---------------------|:----------------- |----------------------------------------|
| `pipelining` | `boolean()` | `false` | HTTP pipelining |
| `max_pipeline_length` | `non_neg_integer()` | 100 | |
| `pool_size` | `pos_integer()` | `erlang:system_info(schedulers)` | Typically one port executable per core |
| `pool_type` | `round_robin | hash` | `round_robin` | Hash is potentially useful when pipelining |
#### Metrics
* ok
* error
* total_time
* curl_time
* namelookup_time
* connect_time
* appconnect_time
* pretransfer_time
* starttransfer_time
### Dependencies
#### Ubuntu Trusty
```sh
sudo apt-get install git libwxgtk2.8-0 libwxbase2.8-0 libevent-dev libcurl4-openssl-dev libcurl4-openssl-dev
wget http://packages.erlang-solutions.com/site/esl/esl-erlang/FLAVOUR_1_esl/esl-erlang_18.0-1~ubuntu~trusty_amd64.deb
sudo dpkg -i esl-erlang_18.0-1~ubuntu~trusty_amd64.deb
```
#### OSX
```sh
brew install --with-c-ares --with-nghttp2 curl
brew install libevent
```
### Building
```sh
make
make test
```
[travis_ci]: https://travis-ci.org/puzza007/katipo
[travis_ci_image]: https://travis-ci.org/puzza007/katipo.png