The high-level API.
Req is composed of:
Req- the high-level API (you're here!)Req.Request- the low-level API and the request structReq.Test- the testing conveniences
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."The request that was sent is available in resp.request:
iex> resp = Req.get!("https://httpbingo.org/basic-auth/foo/bar", auth: {:basic, "foo:bar"})
iex> resp.request.headers["authorization"]
["Basic Zm9vOmJhcg=="]
iex> resp.status
200Making a POST request with Req.post!/2:
iex> Req.post!("https://httpbingo.org/post", form: [comments: "hello!"]).body["form"]
%{"comments" => ["hello!"]}Set connection timeout:
iex> resp = Req.get!("https://httpbingo.org", connect_options: [timeout: 100])
iex> resp.status
200See Req.Finch for more connection related options and usage examples.
Stream request body:
iex> stream = Stream.duplicate("foo", 3)
iex> Req.post!("https://httpbingo.org/post", body: stream, headers: [content_type: "text/plain"]).body["data"]
"foofoofoo"Stream response body using Req.stream/4:
iex> {:ok, resp, acc} =
...> Req.stream(
...> "http://httpbingo.org/stream/2",
...> [],
...> fn data, _resp, acc ->
...> IO.inspect(data)
...> {:cont, acc}
...> end,
...> decoders: [text: :ndjson] # endpoint sends content-type: text/plain
...> # so let's force ndjson.
...> )
# Output: %{"id" => 0, ...}
# Output: %{"id" => 1, ...}
iex> resp.status
200
iex> resp.body
nilStream response body into a Collectable:
iex> resp = Req.get!("http://httpbingo.org/stream/2", into: IO.stream())
# output: {"url": "http://httpbingo.org/stream/2", ...}
# output: {"url": "http://httpbingo.org/stream/2", ...}
iex> resp.status
200
iex> resp.body
%IO.Stream{}Stream response body to the current process and parse incoming messages using Req.parse_message/2.
iex> resp = Req.get!("http://httpbingo.org/stream/2", into: :self)
iex> Req.parse_message(resp, receive do message -> message end)
{:ok, [data: "{\"url\": \"http://httpbingo.org/stream/2\", ..., \"id\": 0}\n"]}
iex> Req.parse_message(resp, receive do message -> message end)
{:ok, [data: "{\"url\": \"http://httpbingo.org/stream/2\", ..., \"id\": 1}\n"]}
iex> Req.parse_message(resp, receive do message -> message end)
{:ok, [:done]}
""Same as above, using enumerable API:
iex> resp = Req.get!("http://httpbingo.org/stream/2", into: :self)
iex> resp.body
#Req.Response.Async<...>
iex> Enum.each(resp.body, &IO.puts/1)
# {"url": "http://httpbingo.org/stream/2", ..., "id": 0}
# {"url": "http://httpbingo.org/stream/2", ..., "id": 1}
:okSee :into option in Req.new/1 documentation for more information on response body streaming.
Headers
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.
Note
Most Elixir/Erlang HTTP clients represent headers as lists of tuples like:
[{"content-type", "text/plain"}]For interoperability with those, use
Req.get_headers_list/1.
Summary
Functions
Returns default options.
Sets default options for Req.new/1.
Returns request/response headers as list.
Updates a request struct.
Returns a new request struct with built-in steps.
Functions (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.
Streams an HTTP request.
Functions (Async Response)
Cancels an asynchronous response.
Parses asynchronous response body message.
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://httpbingo.org")
iex> Req.get!("/statuses/201").status
201
iex> Req.new() |> Req.get!(url: "/statuses/201").status
201
@spec get_headers_list(Req.Request.t() | Req.Response.t()) :: [{binary(), binary()}]
Returns request/response headers as list.
Examples
iex> req = Req.Request.new(headers: %{"accept" => ["application/json"]})
iex> Req.get_headers_list(req)
[{"accept", "application/json"}]
iex> resp = Req.Response.new(headers: %{"content-type" => ["application/json"]})
iex> Req.get_headers_list(resp)
[{"content-type", "application/json"}]
@spec merge(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://httpbingo.org")
iex> req = Req.merge(req, auth: {:basic, "alice:secret"})
iex> req.options[:base_url]
"https://httpbingo.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.merge(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.merge(req, headers: %{authorization: "bearer bar"})
iex> req.headers
%{"authorization" => ["bearer bar"]}Similarly to headers, :params are merged too:
req = Req.new(url: "https://httpbingo.org/anything", params: [a: 1, b: 1])
req = Req.merge(req, params: [a: 2])
Req.get!(req).body["args"]
#=> %{"a" => ["2"], "b" => ["1"]}
@spec new(request :: url() | keyword() | Req.Request.t(), options :: keyword()) :: Req.Request.t()
Returns a new request struct with built-in steps.
See request/2, as well as get/2, post/2, and similar functions for
making requests.
Also 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_agentbecomes"user-agent".string header names are downcased.
%DateTime{}header values are encoded as "HTTP date".
If you set
:headersoptions both inReq.new/1andrequest/2, the header lists are merged.See also "Headers" section in the module documentation.
:body- the request body.Can be one of:
nil- no body is sent with the request.iodata- request body as "IO data".enumerable- stream request body chunks emitted by the givenEnumerable.req_body_fun- stream request body chunks from a 1-arity function.Only supported in
Req.stream/4.The function receives the accumulator passed to
Req.stream/4and should return one of:{:data, chunk, acc}- Emit request bodychunkand continue streaming.{:done, chunk, acc}- emit the final request bodychunk.accis passed to the response streaming function.{:done, acc}- request body streaming is done.accis passed to the response streaming function.{:halt, acc}- cancel request. On HTTP/1, this closes the connection.{:error, exception, acc}- cancel request and return{:error, exception, resp, acc}fromReq.stream/4.
:private- a map reserved for libraries and frameworks to use. The keys must be atoms.
Additional URL options:
:base_url- if set, the request URL is prepended with this base URL (viaput_base_urlstep.):params- if set, appends parameters to the request query string (viaput_paramsstep.):path_params- if set, uses a templated request path (viaput_path_paramsstep.):path_params_style(available since v0.5.1) - how path params are expressed (viaput_path_paramsstep). Can be one of::colon- (default) for Plug-style parameters, such as:codeinhttps://httpbingo.org/status/:code.:curly- for OpenAPI-style parameters, such as{code}inhttps://httpbingo.org/status/{code}.
Authentication options:
:auth- sets request authentication (viaReq.Authstep.)Can be one of:
{:basic, userinfo}- uses Basic HTTP authentication.{:digest, userinfo}- uses Digest 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.&fun/0- a function that returns one of the above (such as a{:bearer, token}).{mod, fun, args}- an MFArgs tuple that returns one of the above (such as a{:bearer, token}).
Request body encoding options (encode_body):
:form- if set, encodes the request body asapplication/x-www-form-urlencoded:form_multipart- if set, encodes the request body asmultipart/form-data.:json- if set, encodes the request body as JSON
Other request body options:
:compress_body- if set totrue, compresses the request body using gzip (viacompress_bodystep.) Defaults tofalse.
Other request options:
:user_agent- sets theuser-agentrequest header, seeReq.Steps.put_user_agent/1.:range- sets therangerequest header, seeReq.Steps.put_range/1.
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".:datetime- the request datetime, defaults toDateTime.utc_now(:second).
Response body options:
:compressed- if set totrue, asks the server to return a compressed response and decompresses it. Defaults tofalse.Note: the response body is decompressed with no size limit, so a small response can expand into many gigabytes. A malicious or compromised server can exploit this to exhaust memory and crash the client (a decompression bomb / denial of service), so only set
compressed: truefor endpoints you trust.:raw- if set totrue, disables body decompression and automatic decoding (seeReq.DecompressandReq.Decode). Defaults tofalse.:decode_body- if set tofalse, disables automatic response body decoding. Defaults totrue.:decoders- the list of decoders to use for automatic response body decoding. Defaults to[:json, :json_api, :ndjson, :sse]. SeeReq.Decodefor the supported formats and how to add custom decoders.:into- where to send the response body. It can be one of:nil- (default) read the whole response body and store it in theresponse.bodyfield.collectable- stream response body into aCollectable.t/0. For example:into: File.stream!("path")Note that the collectable is only used, if the response status is 200. In other cases, the body is accumulated and processed as usual.
:self- stream response body into the current process mailbox.Received messages should be parsed with
Req.parse_message/2.response.bodyis set to opaque data structureReq.Response.Asyncwhich implementsEnumerablethat receives and automatically parses messages. See module documentation for example usage.If the request is sent using HTTP/1, an extra process is spawned to consume messages from the underlying socket. On both HTTP/1 and HTTP/2 the messages are sent to the current process as soon as they arrive, as a firehose. If you wish to maximize request rate or have more control over how messages are streamed, use
Req.stream/4orinto: collectableinstead.
Note:
Req.stream/4does not support:intooption.
Response redirect options (Req.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_trustedis set totrue, credentials will be sent to any host. Defaults tofalse.:redirect_log_level- the log level to emit redirect logs at. Can also be set tofalseto disable logging these messages. Defaults to:debug.:max_redirects- the maximum number of redirects, defaults to10.
Other response options:
:expect- the expected HTTP response status (viaReq.Expectstep). Can be an integer, a range, or a list of integers/ranges.:checksum- if set, this is the expected response body checksum, seeReq.Checksum.
Retry options (Req.Retry step):
:retry- can be one of the following::safe_transient(default) - retry safe (GET/HEAD) requests on one of:HTTP 408/429/500/502/503/504 responses
Req.TransportErrorwithreason: :timeout | :econnrefused | :closedReq.HTTPErrorwithprotocol: :http2, reason: :unprocessed | :pool_not_available
:transient- same as:safe_transientexcept retries all HTTP methods (POST, DELETE, etc.)fun- a 2-arity function that accepts aReq.Requestand either aReq.Responseor an exception struct and returns one of the following:true- retry using the default delay described under:retry_delaybelow.{: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 of theRetry-Afterheader on HTTP 429/503 responses. If the header is not set, the default delay follows a simple exponential backoff with jitter, for example: 0.949s, 1.97s, 3.87s, 7.55s, ...:retry_delaycan 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 tofalseto disable logging these messages. Defaults to:warning.:max_retries- maximum number of retry attempts, defaults to3(for a total of4requests to the server, including the initial one.)
Request adapters:
:adapter- adapter to use to make the actual HTTP request. See:adapterfield description in theReq.Requestmodule documentation for more information.The default is
Req.Finch.:plug- if set, calls the given plug instead of making an HTTP request over the network (via theReq.Plugadapter).The plug can be one of:
Finch options (Req.Finch adapter), see Finch.start_link/1 for options:
:finch- options for the Finch adapter. Defaults to a pool automatically started by Req. Can include::name- the name of the Finch pool.Finch request options, e.g.
:pool_tag,:pool_timeout,:receive_timeout. SeeFinch.Request.build_opt/0andFinch.request_opt/0for more information.Finch pool options, e.g.:
:conn_max_idle_time,:pool_max_idle_time,:conn_opts. SeeFinch.start_link/1for more information.Finch pool options cannot be mixed with
:nameoption.
Examples:
Req.get!("https://httpbingo.org/json", finch: [name: MyFinch]) Req.get!("https://httpbingo.org/json", finch: [name: MyFinch, pool_tag: :bulk]) Req.get!("https://httpbingo.org/json", finch: [conn_max_idle_time: 10_000]):connect_options- dynamically starts (or re-uses already started) Finch pool with the given connection options (seeMint.HTTP.connect/4for options)::timeout- socket connect timeout in milliseconds, defaults to30_000.:protocols- the HTTP protocols to use, defaults to[:http1].:hostname- Mint explicit hostname.:transport_opts- Mint transport options.:proxy_headers- Mint proxy headers.:proxy- Mint HTTP/1 proxy settings, a{scheme, address, port, options}tuple.:client_settings- Mint HTTP/2 client settings.
:inet6- if set to true, uses IPv6. Defaults tofalse.:receive_timeout- socket receive timeout in milliseconds, defaults to15_000.:request_timeout- response timeout in milliseconds, defaults to:infinity. SeeFinch.request/3.: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.
Examples
iex> req = Req.new(url: "https://elixir-lang.org")
iex> req.method
:get
iex> URI.to_string(req.url)
"https://elixir-lang.org"With a url and options:
iex> req = Req.new("https://elixir-lang.org", method: :head)
iex> req.method
:head
Functions (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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.delete("https://httpbingo.org/anything")
iex> resp.body["method"]
"DELETE"With options:
iex> {:ok, resp} = Req.delete(url: "https://httpbingo.org/anything")
iex> resp.body["method"]
"DELETE"With request struct:
iex> req = Req.new(url: "https://httpbingo.org/anything", headers: [content_type: "text/plain"])
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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> Req.delete!("https://httpbingo.org/anything").body["method"]
"DELETE"With options:
iex> Req.delete!(url: "https://httpbingo.org/anything").body["method"]
"DELETE"With request struct:
iex> req = Req.new(url: "https://httpbingo.org/anything", headers: [content_type: "text/plain"])
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
Keywordoptions;a
Req.Requeststruct
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
200With 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
Keywordoptions;a
Req.Requeststruct
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
200With 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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.head("https://httpbingo.org/status/201")
iex> resp.status
201With options:
iex> {:ok, resp} = Req.head(url: "https://httpbingo.org/status/201")
iex> resp.status
201With request struct:
iex> req = Req.new(base_url: "https://httpbingo.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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> Req.head!("https://httpbingo.org/status/201").status
201With options:
iex> Req.head!(url: "https://httpbingo.org/status/201").status
201With request struct:
iex> req = Req.new(base_url: "https://httpbingo.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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.patch("https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"])
iex> resp.body["data"]
"hello!"With options:
iex> {:ok, resp} = Req.patch(url: "https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"])
iex> resp.body["data"]
"hello!"With request struct:
iex> req = Req.new(url: "https://httpbingo.org/anything", headers: [content_type: "text/plain"])
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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> Req.patch!("https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"]).body["data"]
"hello!"With options:
iex> Req.patch!(url: "https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"]).body["data"]
"hello!"With request struct:
iex> req = Req.new(url: "https://httpbingo.org/anything", headers: [content_type: "text/plain"])
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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> {:ok, resp} =
...> Req.post(
...> "https://httpbingo.org/anything",
...> body: "hello!",
...> headers: [content_type: "text/plain"]
...> )
iex> resp.body["data"]
"hello!"
iex> {:ok, resp} = Req.post("https://httpbingo.org/anything", form: [x: 1])
iex> resp.body["form"]
%{"x" => ["1"]}
iex> {:ok, resp} = Req.post("https://httpbingo.org/anything", json: %{x: 2})
iex> resp.body["json"]
%{"x" => 2}With options:
iex> {:ok, resp} = Req.post(url: "https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"])
iex> resp.body["data"]
"hello!"With request struct:
iex> req = Req.new(url: "https://httpbingo.org/anything", headers: [content_type: "text/plain"])
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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> Req.post!("https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"]).body["data"]
"hello!"
iex> Req.post!("https://httpbingo.org/anything", form: [x: 1]).body["form"]
%{"x" => ["1"]}
iex> Req.post!("https://httpbingo.org/anything", json: %{x: 2}).body["json"]
%{"x" => 2}With options:
iex> Req.post!(url: "https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"]).body["data"]
"hello!"With request struct:
iex> req = Req.new(url: "https://httpbingo.org/anything", headers: [content_type: "text/plain"])
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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> {:ok, resp} = Req.put("https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"])
iex> resp.body["data"]
"hello!"With options:
iex> {:ok, resp} = Req.put(url: "https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"])
iex> resp.body["data"]
"hello!"With request struct:
iex> req = Req.new(url: "https://httpbingo.org/anything", headers: [content_type: "text/plain"])
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
Keywordoptions;a
Req.Requeststruct
See new/1 for a list of available options.
Examples
With URL:
iex> Req.put!("https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"]).body["data"]
"hello!"With options:
iex> Req.put!(url: "https://httpbingo.org/anything", body: "hello!", headers: [content_type: "text/plain"]).body["data"]
"hello!"With request struct:
iex> req = Req.new(url: "https://httpbingo.org/anything", headers: [content_type: "text/plain"])
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
Keywordoptions; - a
Req.Requeststruct
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
200With request struct:
iex> req = Req.new(url: "https://api.github.com/repos/elixir-lang/elixir")
iex> Req.request!(req).status
200
@spec stream(req, acc, fun, options) :: {:ok, resp, acc} | {:error, err, resp, acc} when req: url() | keyword() | Req.Request.t(), resp: Req.Response.t(), err: Exception.t(), acc: term(), fun: (data :: term(), resp, acc -> {:cont, acc} | {:halt, acc}), options: keyword()
Streams an HTTP request.
req can be one of:
- an url (
StringorURI); - a
Keywordoptions; - a
Req.Requeststruct
acc is the initial accumulator. fun receives response body chunk, the response struct, and
accumulator. fun must return {:cont, acc} to continue streaming or {:halt, acc} to cancel
the request (on HTTP/1 cancelling the request closes the connection):
fn data, resp, acc ->
{:cont, acc} | {:halt, acc}
enddata is automatically decoded for some formats, including NDJSON and SSE (Server-Sent Events).
See Req.Decode for more information.
Req.stream/4 returns {:ok, resp, acc} or {:error, err, resp, acc}.
See new/1 for a list of available options.
Examples
Returns recent Wikipedia changes:
iex> {:ok, resp, acc} =
...> Req.stream(
...> "https://stream.wikimedia.org/v2/stream/recentchange",
...> [],
...> fn event, _resp, acc ->
...> %{"type" => type, "title" => title} = JSON.decode!(event.data)
...> event = {type, title}
...>
...> if length(acc) < 1 do
...> {:cont, [event | acc]}
...> else
...> {:halt, [event | acc]}
...> end
...> end
...> )
iex> resp.status
200
iex> resp.body
nil
iex> Enum.reverse(acc)
[
{"edit", "File:Glacier National Park (GeoDIL number - 2068).jpg"},
{"categorize", "Category:Coins of Merovingian dynasty from Gallica"}
]Returns an error:
iex> {:error, err, resp, acc} =
...> Req.stream(
...> "http://localhost:9999",
...> nil,
...> fn data, _resp, acc -> dbg(data); {:cont, acc} end,
...> retry: false
...> )
iex> err
%Req.TransportError{reason: :econnrefused}
iex> resp.status
nil
iex> to_string(resp.request.url)
"http://localhost:9999"
Functions (Async Response)
Cancels an asynchronous response.
An asynchronous response is a result of request with into: :self.
See also Req.Response.Async.
Examples
iex> resp = Req.get!("http://httpbingo.org/stream/2", into: :self)
iex> Req.cancel_async_response(resp)
:ok
Parses asynchronous response body message.
A request with option :into set to :self returns response with asynchronous body.
In that case, Req sends chunks to the calling process as messages. You'd typically
get them using receive/1 or handle_info/2 in a GenServer.
These messages should be parsed using this function. The possible return values are:
{:ok, chunks}- where a chunk can be{:data, binary},{:trailers, trailers}, or:done.{:error, reason}- an error occurred:unknown- the message was not meant for this response.
See also Req.Response.Async.
Examples
iex> resp = Req.get!("http://httpbingo.org/stream/2", into: :self)
iex> Req.parse_message(resp, receive do message -> message end)
{:ok, [data: "{"url": "http://httpbingo.org/stream/2", ..., "id": 0}\n"]}
iex> Req.parse_message(resp, receive do message -> message end)
{:ok, [data: "{"url": "http://httpbingo.org/stream/2", ..., "id": 1}\n"]}
iex> Req.parse_message(resp, receive do message -> message end)
{:ok, [:done]}
iex> Req.parse_message(resp, :other)
:unknown