Skip to content
/ erqwest Public

An experimental erlang HTTP client wrapping reqwest

Notifications You must be signed in to change notification settings

dlesl/erqwest

Repository files navigation

erqwest

Hex pm

An erlang wrapper for reqwest using rustler. Map-based interface inspired by katipo.

Features

  • HTTP/1.1 and HTTP/2 with connection keepalive/reuse
  • Configurable SSL support, uses system root certificates by default
  • Sync and async interfaces
  • Proxy support
  • Optional cookies support
  • Optional gzip support

Prerequisites

  • Erlang/OTP
  • Rust
  • OpenSSL (not required on mac)

Or use the provided shell.nix if you have nix installed.

Usage

Start a client

ok = application:ensure_started(erqwest),
ok = erqwest:start_client(default).

This registers a client under the name default. The client maintains an internal connection pool.

Synchronous interface

No streaming

{ok, #{status := 200, body := Body}} = 
    erqwest:get(default, <<"https://httpbin.org/get">>),

{ok, #{status := 200, body := Body1}} =
    erqwest:post(default, <<"https://httpbin.org/post">>,
                 #{body => <<"data">>}).

Stream request body

{handle, H} = erqwest:post(default, <<"https://httpbin.org/post">>,
                           #{body => stream}),
ok = erqwest:send(H, <<"data, ">>),
ok = erqwest:send(H, <<"more data.">>),
{ok, #{body := Body}} = erqwest:finish_send(H).

Stream response body

{ok, #{body := Handle}} = erqwest:get(default, <<"https://httpbin.org/stream-bytes/1000">>,
                                      #{response_body => stream}),
ReadAll = fun Self() ->
              case erqwest:read(Handle, #{length => 0}) of
                {ok, Data} ->
                  [Data];
                {more, Data} ->
                  [Data|Self()]
              end
          end,
1000 = iolist_size(ReadAll()).

Conditionally consume response body

{ok, Resp} = erqwest:get(default, <<"https://httpbin.org/status/200,500">>,
                         #{response_body => stream}),
case Resp of
  #{status := 200, body := Handle} ->
    {ok, <<>>} = erqwest:read(Handle),
  #{status := BadStatus, body := Handle} ->
    %% ensures the connection is closed/can be reused immediately
    erqwest:cancel(Handle),
    io:format("Status is ~p, not interested~n", [BadStatus])
end.

Asynchronous interface

erqwest_async:req(default, self(), Ref=make_ref(), 
                  #{method => get, url => <<"https://httpbin.org/get">>}),
receive
    {erqwest_response, Ref, reply, #{body := Body}} -> Body
end.

See the docs for more details and and the test suite for more examples.

About

An experimental erlang HTTP client wrapping reqwest

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •