Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/puzza007/katipo
HTTP2 client for Erlang based on libcurl and libevent
https://github.com/puzza007/katipo
curl erlang hacktoberfest http-client http2 http2-client libcurl libcurl-multi libevent
Last synced: 22 days ago
JSON representation
HTTP2 client for Erlang based on libcurl and libevent
- Host: GitHub
- URL: https://github.com/puzza007/katipo
- Owner: puzza007
- License: other
- Created: 2015-08-05T08:28:14.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2024-05-27T21:17:46.000Z (5 months ago)
- Last Synced: 2024-10-01T02:41:11.958Z (about 1 month ago)
- Topics: curl, erlang, hacktoberfest, http-client, http2, http2-client, libcurl, libcurl-multi, libevent
- Language: Erlang
- Homepage:
- Size: 2.69 MB
- Stars: 122
- Watchers: 4
- Forks: 19
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
katipo
=====An HTTP/HTTP2 client library for Erlang built around libcurl-multi and libevent.
### Status
![build status](https://github.com/puzza007/katipo/actions/workflows/ci.yml/badge.svg)
[![Hex pm](http://img.shields.io/hexpm/v/katipo.svg?style=flat)](https://hex.pm/packages/katipo)
[![Hex Docs](https://img.shields.io/badge/hex-docs-blue.svg)](https://hexdocs.pm/katipo)### Usage
```erlang
{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
```erlang
{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
```erlang
-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
| Option | Values | Default | Notes |
|:-------|:-------|:--------|:------|
| `mod_metrics` |folsom | exometer | noop
| `noop` | see [erlang-metrics](https://github.com/benoitc/erlang-metrics) |#### Request options
| Option | Type | Default | Notes |
|:------------------------|:------------------------------------|:------------|:------------------------------------------------------------------------------------|
| `headers` | `[{binary(), iodata()}]` | `[]` | |
| `cookiejar` | opaque (returned in response) | `[]` | |
| `body` | `iodata()` | `<<>>` | |
| `connecttimeout_ms` | `pos_integer()` | 30000 | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_CONNECTTIMEOUT.html) |
| `followlocation` | `boolean()` | `false` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_FOLLOWLOCATION.html) |
| `ssl_verifyhost` | `boolean()` | `true` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html) |
| `ssl_verifypeer` | `boolean()` | `true` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html) |
| `capath` | `binary()` | `undefined` | |
| `cacert` | `binary()` | `undefined` | |
| `timeout_ms` | `pos_integer()` | 30000 | |
| `maxredirs` | `non_neg_integer()` | 9 | |
| `proxy` | `binary()` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_PROXY.html) |
| `return_metrics` | `boolean()` | `false` | |
| `tcp_fastopen` | `boolean()` | `false` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_TCP_FASTOPEN.html) curl >= 7.49.0 |
| `interface` | `binary()` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_INTERFACE.html) |
| `unix_socket_path` | `binary()` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_UNIX_SOCKET_PATH.html) curl >= 7.40.0 |
| `lock_data_ssl_session` | `boolean()` | `false` | [docs](https://curl.haxx.se/libcurl/c/curl_share_setopt.html) curl >= 7.23.0 |
| `doh_url` | `binary()` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_DOH_URL.html) curl >= 7.62.0 |
| `http_version` | `curl_http_version_none`
`curl_http_version_1_0`
`curl_http_version_1_1`
`curl_http_version_2_0`
`curl_http_version_2tls`
`curl_http_version_2_prior_knowledge` | `curl_http_version_none` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_HTTP_VERSION.html) curl >= 7.62.0 |
| `sslcert` | `binary()` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_SSLCERT.html) |
| `sslkey` | `binary()` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_SSLKEY.html) |
| `sslkey_blob` | `binary()` (DER format) | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_SSLKEY_BLOB.html) curl >= 7.71.0 |
| `keypasswd` | `binary()` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_KEYPASSWD.html) |
| `http_auth` | `basic`
`digest`
`ntlm`
`negotiate` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html) |
| `userpwd` | `binary()` | `undefined` | [docs](https://curl.haxx.se/libcurl/c/CURLOPT_USERPWD.html) |#### Responses
```erlang
{ok, #{status := pos_integer(),
headers := headers(),
cookiejar := cookiejar(),
body := body(),
metrics => proplist()}}{error, #{code := atom(), message := binary()}}
```#### Pool Options
| Option | Type | Default | Note |
|:------------------------|:------------------------------|:-------------|:-----------------------------------------------------------------------------------------------|
| `pipelining` | `nothing`
`http1`
`multiplex` | `nothing` | HTTP pipelining [CURLMOPT_PIPELINING](https://curl.haxx.se/libcurl/c/CURLMOPT_PIPELINING.html) |
| `max_pipeline_length` | `non_neg_integer()` | 100 | |
| `max_total_connections` | `non_neg_integer()` | 0 (no limit) | [docs](https://curl.haxx.se/libcurl/c/CURLMOPT_MAX_TOTAL_CONNECTIONS.html) |#### Metrics
* ok
* error
* status.XXX
* total_time
* curl_time
* namelookup_time
* connect_time
* appconnect_time
* pretransfer_time
* redirect_time
* starttransfer_time### System dependencies
* libevent-dev
* libcurl4-openssl-dev
* make
* curl
* libssl-dev
* gcc## Testing
The official Erlang Docker [image](https://hub.docker.com/_/erlang)
has everything needed to build and test Katipo### TODO
* A more structured way to ifdef features based on curl version