Maxwell is an HTTP client that provides a common interface over :httpc, :ibrowse, :hackney.
The simplest way to use Maxwell is by creating a module which will be your API wrapper, using Maxwell.Builder
:
defmodule GitHubClient do
# Generates `get/1`, `get!/1`, `patch/1`, `patch!/1` public functions
# You can omit the list and functions for all HTTP methods will be generated
use Maxwell.Builder, ~w(get patch)a
# For a complete list of middlewares, see the docs
middleware Maxwell.Middleware.BaseUrl, "https://api.github.com"
middleware Maxwell.Middleware.Headers, %{"content-type" => "application/vnd.github.v3+json", "user-agent" => "zhongwenool"}
middleware Maxwell.Middleware.Opts, connect_timeout: 3000
middleware Maxwell.Middleware.Json
middleware Maxwell.Middleware.Logger
# adapter can be omitted, and the default will be used (currently :ibrowse)
adapter Maxwell.Adapter.Hackney
# List public repositories for the specified user.
def user_repos(username) do
"/users/#{username}/repos"
|> new()
|> get()
end
# Edit owner repositories
def edit_repo_desc(owner, repo, name, desc) do
"/repos/#{owner}/#{repo}"
|> new()
|> put_req_body(%{name: name, description: desc})
|> patch()
end
end
Maxwell.Builder
injects functions for all supported HTTP methods, in two flavors, the first (e.g. get/1
) will
return {:ok, Maxwell.Conn.t}
or {:error, term, Maxwell.Conn.t}
. The second (e.g. get!/1
) will return
Maxwell.Conn.t
only if the request succeeds and returns a 2xx status code, otherwise it will raise Maxwell.Error
.
The same functions are also exported by the Maxwell
module, which you can use if you do not wish to define a wrapper
module for your API, as shown below:
iex(1)> alias Maxwell.Conn
iex(2)> Conn.new("http://httpbin.org/drip") |>
Conn.put_query_string(%{numbytes: 25, duration: 1, delay: 1, code: 200}) |>
Maxwell.get
{:ok,
%Maxwell.Conn{method: :get, opts: [], path: "/drip",
query_string: %{code: 200, delay: 1, duration: 1, numbytes: 25},
req_body: nil, req_headers: %{}, resp_body: '*************************',
resp_headers: %{"access-control-allow-credentials" => "true",
"access-control-allow-origin" => "*",
"connection" => "keep-alive",
"content-length" => "25",
"content-type" => "application/octet-stream",
"date" => "Sun, 18 Dec 2016 14:32:38 GMT",
"server" => "nginx"}, state: :sent, status: 200,
url: "http://httpbin.org"}}
There are numerous helper functions for the Maxwell.Conn
struct. See it's module docs
for a list of all functions, and detailed info about how they behave.
-
Add maxwell to your list of dependencies in
mix.exs
:def deps do [{:maxwell, "~> 2.3"}] end
-
Ensure maxwell has started before your application:
def application do [applications: [:maxwell]] # also add your adapter(ibrowse, hackney) end
Maxwell has support for different adapters that do the actual HTTP request processing.
Maxwell has built-in support for the httpc Erlang HTTP client.
To use it simply place adapter Maxwell.Adapter.Httpc
in your API client definition.
Maxwell has built-in support for the ibrowse Erlang HTTP client.
To use it simply place adapter Maxwell.Adapter.Ibrowse
in your API client definition.
NOTE: Remember to include :ibrowse
in your applications list.
Maxwell has built-in support for the hackney Erlang HTTP client.
To use it simply place adapter Maxwell.Adapter.Hackney
in your API client definition.
NOTE: Remember to include :hackney
in your applications list.
Sets the base url for all requests.
Sets default headers for all requests.
Enforces that all header keys share a specific casing style, e.g. lower-case, upper-case, or title-case.
Sets adapter options for all requests.
Decodes rel links in the response, and places them in the :rels
key of the Maxwell.Conn
struct.
Logs information about all requests and responses. You can set :log_level
to log the information at that level.
Encodes all requests as application/json
and decodes all responses as application/json
.
Encodes all requests as application/json
.
Decodes all responses as application/json
.
NOTE: The *Json
middlewares require Poison as dependency, versions 2.x and 3.x are supported.
You may provide your own encoder/decoder by providing the following options:
# For the EncodeJson module
middleware Maxwell.Middleware.EncodeJson,
encode_content_type: "text/javascript",
encode_func: &other_json_lib.encode/1]
# For the DecodeJson module
middleware Maxwell.Middleware.DecodeJson,
decode_content_types: ["yourowntype"],
decode_func: &other_json_lib.decode/1]
# Both sets of options can be provided to the Json module
Take a look at the Maxwell.Middleware for more information on the behaviour. For example implementations take a look at any of the middleware modules in the repository.
Contributions are more than welcome!
Check the issues tracker for anything marked "help wanted", and post a comment that you are planning to begin working on the issue. We can then provide guidance on implementation if necessary.
See the LICENSE file for license rights and limitations (MIT).