View Source Req (req v0.4.11)
The high-level API.
Req is composed of three main pieces:
Req
- the high-level API (you're here!)Req.Request
- the low-level API and the request structReq.Steps
- the collection of built-in steps
The high-level API is what most users of Req will use most of the time.
Examples
Making a GET request with Req.get!/1
:
iex> Req.get!("https://api.github.com/repos/wojtekmach/req").body["description"]
"Req is a batteries-included HTTP client for Elixir."
Same, but by explicitly building request struct first:
iex> req = Req.new(base_url: "https://api.github.com")
iex> Req.get!(req, url: "/repos/wojtekmach/req").body["description"]
"Req is a batteries-included HTTP client for Elixir."
Making a POST request with Req.post!/2
:
iex> Req.post!("https://httpbin.org/post", form: [comments: "hello!"]).body["form"]
%{"comments" => "hello!"}
Stream request body:
iex> stream = Stream.duplicate("foo", 3)
iex> Req.post!("https://httpbin.org/post", body: stream).body["data"]
"foofoofoo"
Stream response body using a callback:
iex> resp =
...> Req.get!("http://httpbin.org/stream/2", into: fn {:data, data}, {req, resp} ->
...> IO.puts(data)
...> {:cont, {req, resp}}
...> end)
# output: {"url": "http://httpbin.org/stream/2", ...}
# output: {"url": "http://httpbin.org/stream/2", ...}
iex> resp.status
200
iex> resp.body
""
Stream response body into a Collectable
:
iex> resp = Req.get!("http://httpbin.org/stream/2", into: IO.stream())
# output: {"url": "http://httpbin.org/stream/2", ...}
# output: {"url": "http://httpbin.org/stream/2", ...}
iex> resp.status
200
iex> resp.body
%IO.Stream{}
Header Names
The HTTP specification requires that header names should be case-insensitive. Req allows two ways to access the headers; using functions and by accessing the data directly:
iex> Req.Response.get_header(response, "content-type")
["text/html"]
iex> response.headers["content-type"]
["text/html"]
While we can ensure case-insensitive handling in the former case, we can't in the latter. For this reason, Req made the following design choices:
header names are stored as downcased
functions like
Req.Request.get_header/2
,Req.Request.put_header/3
,Req.Response.get_header/2
,Req.Response.put_header/3
, etc automatically downcase the given header name.
Summary
Making Requests
Makes a DELETE request and returns a response or an error.
Makes a DELETE request and returns a response or raises an error.
Makes a GET request and returns a response or an error.
Makes a GET request and returns a response or raises an error.
Makes a HEAD request and returns a response or an error.
Makes a HEAD request and returns a response or raises an error.
Makes a PATCH request and returns a response or an error.
Makes a PATCH request and returns a response or raises an error.
Makes a POST request and returns a response or an error.
Makes a POST request and returns a response or raises an error.
Makes a PUT request and returns a response or an error.
Makes a PUT request and returns a response or raises an error.
Makes an HTTP request and returns a response or an error.
Makes an HTTP request and returns a response or raises an error.
Making Requests
@spec delete(url() | keyword() | Req.Request.t(), options :: keyword()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
Makes a DELETE request and returns a response or an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.delete("https://httpbin.org/anything")
iex> resp.body["method"]
"DELETE"
With options:
iex> {:ok, resp} = Req.delete(url: "https://httpbin.org/anything")
iex> resp.body["method"]
"DELETE"
With request struct:
iex> req = Req.new(url: "https://httpbin.org/anything")
iex> {:ok, resp} = Req.delete(req)
iex> resp.body["method"]
"DELETE"
@spec delete!(url() | keyword() | Req.Request.t(), options :: keyword()) :: Req.Response.t()
Makes a DELETE request and returns a response or raises an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> Req.delete!("https://httpbin.org/anything").body["method"]
"DELETE"
With options:
iex> Req.delete!(url: "https://httpbin.org/anything").body["method"]
"DELETE"
With request struct:
iex> req = Req.new(url: "https://httpbin.org/anything")
iex> Req.delete!(req).body["method"]
"DELETE"
@spec get(url() | keyword() | Req.Request.t(), options :: keyword()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
Makes a GET request and returns a response or an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.get("https://api.github.com/repos/wojtekmach/req")
iex> resp.body["description"]
"Req is a batteries-included HTTP client for Elixir."
With options:
iex> {:ok, resp} = Req.get(url: "https://api.github.com/repos/wojtekmach/req")
iex> resp.status
200
With request struct:
iex> req = Req.new(base_url: "https://api.github.com")
iex> {:ok, resp} = Req.get(req, url: "/repos/elixir-lang/elixir")
iex> resp.status
200
@spec get!(url() | keyword() | Req.Request.t(), options :: keyword()) :: Req.Response.t()
Makes a GET request and returns a response or raises an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> Req.get!("https://api.github.com/repos/wojtekmach/req").body["description"]
"Req is a batteries-included HTTP client for Elixir."
With options:
iex> Req.get!(url: "https://api.github.com/repos/wojtekmach/req").status
200
With request struct:
iex> req = Req.new(base_url: "https://api.github.com")
iex> Req.get!(req, url: "/repos/elixir-lang/elixir").status
200
@spec head(url() | keyword() | Req.Request.t(), options :: keyword()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
Makes a HEAD request and returns a response or an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.head("https://httpbin.org/status/201")
iex> resp.status
201
With options:
iex> {:ok, resp} = Req.head(url: "https://httpbin.org/status/201")
iex> resp.status
201
With request struct:
iex> req = Req.new(base_url: "https://httpbin.org")
iex> {:ok, resp} = Req.head(req, url: "/status/201")
iex> resp.status
201
@spec head!(url() | keyword() | Req.Request.t(), options :: keyword()) :: Req.Response.t()
Makes a HEAD request and returns a response or raises an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> Req.head!("https://httpbin.org/status/201").status
201
With options:
iex> Req.head!(url: "https://httpbin.org/status/201").status
201
With request struct:
iex> req = Req.new(base_url: "https://httpbin.org")
iex> Req.head!(req, url: "/status/201").status
201
@spec patch(url() | keyword() | Req.Request.t(), options :: keyword()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
Makes a PATCH request and returns a response or an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.patch("https://httpbin.org/anything", body: "hello!")
iex> resp.body["data"]
"hello!"
With options:
iex> {:ok, resp} = Req.patch(url: "https://httpbin.org/anything", body: "hello!")
iex> resp.body["data"]
"hello!"
With request struct:
iex> req = Req.new(url: "https://httpbin.org/anything")
iex> {:ok, resp} = Req.patch(req, body: "hello!")
iex> resp.body["data"]
"hello!"
@spec patch!(url() | keyword() | Req.Request.t(), options :: keyword()) :: Req.Response.t()
Makes a PATCH request and returns a response or raises an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> Req.patch!("https://httpbin.org/anything", body: "hello!").body["data"]
"hello!"
With options:
iex> Req.patch!(url: "https://httpbin.org/anything", body: "hello!").body["data"]
"hello!"
With request struct:
iex> req = Req.new(url: "https://httpbin.org/anything")
iex> Req.patch!(req, body: "hello!").body["data"]
"hello!"
@spec post(url() | keyword() | Req.Request.t(), options :: keyword()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
Makes a POST request and returns a response or an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.post("https://httpbin.org/anything", body: "hello!")
iex> resp.body["data"]
"hello!"
iex> {:ok, resp} = Req.post("https://httpbin.org/anything", form: [x: 1])
iex> resp.body["form"]
%{"x" => "1"}
iex> {:ok, resp} = Req.post("https://httpbin.org/anything", json: %{x: 2})
iex> resp.body["json"]
%{"x" => 2}
With options:
iex> {:ok, resp} = Req.post(url: "https://httpbin.org/anything", body: "hello!")
iex> resp.body["data"]
"hello!"
With request struct:
iex> req = Req.new(url: "https://httpbin.org/anything")
iex> {:ok, resp} = Req.post(req, body: "hello!")
iex> resp.body["data"]
"hello!"
@spec post!(url() | keyword() | Req.Request.t(), options :: keyword()) :: Req.Response.t()
Makes a POST request and returns a response or raises an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> Req.post!("https://httpbin.org/anything", body: "hello!").body["data"]
"hello!"
iex> Req.post!("https://httpbin.org/anything", form: [x: 1]).body["form"]
%{"x" => "1"}
iex> Req.post!("https://httpbin.org/anything", json: %{x: 2}).body["json"]
%{"x" => 2}
With options:
iex> Req.post!(url: "https://httpbin.org/anything", body: "hello!").body["data"]
"hello!"
With request struct:
iex> req = Req.new(url: "https://httpbin.org/anything")
iex> Req.post!(req, body: "hello!").body["data"]
"hello!"
@spec put(url() | keyword() | Req.Request.t(), options :: keyword()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
Makes a PUT request and returns a response or an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.put("https://httpbin.org/anything", body: "hello!")
iex> resp.body["data"]
"hello!"
With options:
iex> {:ok, resp} = Req.put(url: "https://httpbin.org/anything", body: "hello!")
iex> resp.body["data"]
"hello!"
With request struct:
iex> req = Req.new(url: "https://httpbin.org/anything")
iex> {:ok, resp} = Req.put(req, body: "hello!")
iex> resp.body["data"]
"hello!"
@spec put!(url() | keyword() | Req.Request.t(), options :: keyword()) :: Req.Response.t()
Makes a PUT request and returns a response or raises an error.
request
can be one of:
- a
String
orURI
; - a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With URL:
iex> Req.put!("https://httpbin.org/anything", body: "hello!").body["data"]
"hello!"
With options:
iex> Req.put!(url: "https://httpbin.org/anything", body: "hello!").body["data"]
"hello!"
With request struct:
iex> req = Req.new(url: "https://httpbin.org/anything")
iex> Req.put!(req, body: "hello!").body["data"]
"hello!"
@spec request(request :: Req.Request.t() | keyword(), options :: keyword()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
Makes an HTTP request and returns a response or an error.
request
can be one of:
- a
Keyword
options; - a
Req.Request
struct
See new/1
for a list of available options.
Examples
With options keywords list:
iex> {:ok, response} = Req.request(url: "https://api.github.com/repos/wojtekmach/req")
iex> response.status
200
iex> response.body["description"]
"Req is a batteries-included HTTP client for Elixir."
With request struct:
iex> req = Req.new(url: "https://api.github.com/repos/elixir-lang/elixir")
iex> {:ok, response} = Req.request(req)
iex> response.status
200
@spec request!(request :: Req.Request.t() | keyword(), options :: keyword()) :: Req.Response.t()
Makes an HTTP request and returns a response or raises an error.
See new/1
for a list of available options.
Examples
With options keywords list:
iex> Req.request!(url: "https://api.github.com/repos/elixir-lang/elixir").status
200
With request struct:
iex> req = Req.new(url: "https://api.github.com/repos/elixir-lang/elixir")
iex> Req.request!(req).status
200
Types
Functions
@spec default_options() :: keyword()
Returns default options.
See default_options/1
for more information.
@spec default_options(keyword()) :: :ok
Sets default options for Req.new/1
.
Avoid setting default options in libraries as they are global.
Examples
iex> Req.default_options(base_url: "https://httpbin.org")
iex> Req.get!("/statuses/201").status
201
iex> Req.new() |> Req.get!(url: "/statuses/201").status
201
@spec new(options :: keyword()) :: Req.Request.t()
Returns a new request struct with built-in steps.
See Req.Request
module documentation for more information on the underlying request struct.
Options
Basic request options:
:method
- the request method, defaults to:get
.:url
- the request URL.:headers
- the request headers as a{key, value}
enumerable (e.g. map, keyword list).The header names should be downcased.
The headers are automatically encoded using these rules:
atom header names are turned into strings, replacing
_
with-
. For example,:user_agent
becomes"user-agent"
.string header names are downcased.
%DateTime{}
header values are encoded as "HTTP date".other header values are encoded with
String.Chars.to_string/1
.
If you set
:headers
options both inReq.new/1
andrequest/2
, the header lists are merged.See also "Header Names" section in the module documentation.
:body
- the request body.Can be one of:
iodata
- send request body eagerlyenumerable
- streamenumerable
as request body
Additional URL options:
:base_url
- if set, the request URL is prepended with this base URL (viaput_base_url
step.):params
- if set, appends parameters to the request query string (viaput_params
step.):path_params
- if set, uses a templated request path (viaput_path_params
step.)
Authentication options:
:auth
- sets request authentication (viaauth
step.)Can be one of:
{:basic, userinfo}
- uses Basic HTTP authentication.{:bearer, token}
- uses Bearer HTTP authentication.:netrc
- load credentials from the default .netrc file.{:netrc, path}
- load credentials frompath
.string
- sets to this value.
:redact_auth
- if set totrue
, whenReq.Request
struct is inspected, authentication credentials are redacted. Defaults totrue
.
Request body options:
:form
- if set, encodes the request body as form data (encode_body
step.):json
- if set, encodes the request body as JSON (encode_body
step.):compress_body
- if set totrue
, compresses the request body using gzip (viacompress_body
step.) Defaults tofalse
.
AWS Signature Version 4 options (put_aws_sigv4
step):
:aws_sigv4
- if set, the AWS options to sign request::access_key_id
- the AWS access key id.:secret_access_key
- the AWS secret access key.:service
- the AWS service.:region
- if set, AWS region. Defaults to"us-east-1"
.
This functionality requires :aws_signature
dependency:
{:aws_signature, "~> 0.3.0"}
Response body options:
:compressed
- if set totrue
, asks the server to return compressed response. (viacompressed
step.) Defaults totrue
.:raw
- if set totrue
, disables automatic body decompression (decompress_body
step) and decoding (decode_body
step.) Defaults tofalse
.:decode_body
- if set tofalse
, disables automatic response body decoding. Defaults totrue
.:decode_json
- options to pass toJason.decode!/2
, defaults to[]
.:into
- where to send the response body. It can be one of:nil
- (default) read the whole response body and store it in theresponse.body
field.fun
- stream response body using a function. The first argument is a{:data, data}
tuple containing the chunk of the response body. The second argument is a{request, response}
tuple. To continue streaming chunks, return{:cont, {req, resp}}
. To cancel, return{:halt, {req, resp}}
. For example:into: fn {:data, data}, {req, resp} -> IO.puts(data) {:cont, {req, resp}} end
collectable
- stream response body into aCollectable.t/0
.
Response redirect options (redirect
step):
:redirect
- if set tofalse
, disables automatic response redirects. Defaults totrue
.:redirect_trusted
- by default, authorization credentials are only sent on redirects with the same host, scheme and port. If:redirect_trusted
is set totrue
, credentials will be sent to any host.:max_redirects
- the maximum number of redirects, defaults to10
.
Retry options (retry
step):
:retry
- can be one of the following::safe_transient
(default) - retry safe (GET/HEAD) requests on HTTP 408/429/500/502/503/504 responses or exceptions withreason
field set to:timeout
/:econnrefused
/:closed
.:transient
- same as:safe_transient
except retries all HTTP methods (POST, DELETE, etc.)fun
- a 2-arity function that accepts aReq.Request
and either aReq.Response
or an exception struct and returns one of the following:true
- retry with the default delay controller by default delay option described below.{:delay, milliseconds}
- retry with the given delay.false/nil
- don't retry.
false
- don't retry.
:retry_delay
- if not set, which is the default, the retry delay is determined by the value ofretry-delay
header on HTTP 429/503 responses. If the header is not set, the default delay follows a simple exponential backoff: 1s, 2s, 4s, 8s, ...:retry_delay
can be set to a function that receives the retry count (starting at 0) and returns the delay, the number of milliseconds to sleep before making another attempt.:retry_log_level
- the log level to emit retry logs at. Can also be set tofalse
to disable logging these messages. Defaults to:error
.:max_retries
- maximum number of retry attempts, defaults to3
(for a total of4
requests to the server, including the initial one.)
Caching options (cache
step):
:cache
- iftrue
, performs HTTP caching. Defaults tofalse
.:cache_dir
- the directory to store the cache, defaults to<user_cache_dir>/req
(see::filename.basedir/3
)
Request adapters:
:adapter
- adapter to use to make the actual HTTP request. See:adapter
field description in theReq.Request
module documentation for more information. Defaults to callingrun_finch
.:plug
- if set, calls the given Plug instead of making an HTTP request over the network (viaput_plug
step).
Finch options (run_finch
step)
:finch
- the Finch pool to use. Defaults to pool automatically started byReq
.:connect_options
- dynamically starts (or re-uses already started) Finch pool with the given connection options::timeout
- socket connect timeout in milliseconds, defaults to30_000
.:protocols
- the HTTP protocols to use, defaults to[:http1, :http2]
, that is default to HTTP/1 but if negotiated, allow HTTP/2 over HTTP/1 connection. To force HTTP/2, setprotocols: [:http2]
.:hostname
- Mint explicit hostname.:transport_opts
- Mint transport options.:proxy_headers
- Mint proxy headers.:proxy
- Mint HTTP/1 proxy settings, a{schema, address, port, options}
tuple.:client_settings
- Mint HTTP/2 client settings.
:inet6
- if set to true, uses IPv6. Defaults tofalse
.:pool_timeout
- pool checkout timeout in milliseconds, defaults to5000
.:receive_timeout
- socket receive timeout in milliseconds, defaults to15_000
.:unix_socket
- if set, connect through the given UNIX domain socket.:finch_private
- a map or keyword list of private metadata to add to the Finch request. May be useful for adding custom data when handling telemetry withFinch.Telemetry
.:finch_request
- a function that executes the Finch request, defaults to usingFinch.request/3
.
Examples
iex> req = Req.new(url: "https://elixir-lang.org")
iex> req.method
:get
iex> URI.to_string(req.url)
"https://elixir-lang.org"
Fake adapter:
iex> fake = fn request ->
...> {request, Req.Response.new(status: 200, body: "it works!")}
...> end
iex>
iex> req = Req.new(adapter: fake)
iex> Req.get!(req).body
"it works!"
@spec update(Req.Request.t(), options :: keyword()) :: Req.Request.t()
Updates a request struct.
See new/1
for a list of available options. Also see Req.Request
module documentation
for more information on the underlying request struct.
Examples
iex> req = Req.new(base_url: "https://httpbin.org")
iex> req = Req.update(req, auth: {:basic, "alice:secret"})
iex> req.options[:base_url]
"https://httpbin.org"
iex> req.options[:auth]
{:basic, "alice:secret"}
Passing :headers
will automatically encode and merge them:
iex> req = Req.new(headers: %{point_x: 1})
iex> req = Req.update(req, headers: %{point_y: 2})
iex> req.headers
%{"point-x" => ["1"], "point-y" => ["2"]}
The same header names are overwritten however:
iex> req = Req.new(headers: %{authorization: "bearer foo"})
iex> req = Req.update(req, headers: %{authorization: "bearer bar"})
iex> req.headers
%{"authorization" => ["bearer bar"]}
Similarly to headers, :params
are merged too:
req = Req.new(url: "https://httpbin.org/anything", params: [a: 1, b: 1])
req = Req.update(req, params: [a: 2])
Req.get!(req).body["args"]
#=> %{"a" => "2", "b" => "1"}