# `Req`
[🔗](https://github.com/wojtekmach/req/blob/v0.8.0-rc.0/lib/req.ex#L1)

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 struct

  * `Req.Auth`, …, `Req.Steps` - a collection of built-in steps.

  * `Req.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
    200

Making 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
    200

See `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
    nil

Stream 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}
    :ok

See `: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 {: .tip}
>
> Most Elixir/Erlang HTTP clients represent headers as lists of tuples like:
>
> ```elixir
> [{"content-type", "text/plain"}]
> ```
>
> For interoperability with those, use
> `Req.get_headers_list/1`.

# `url`

```elixir
@type url() :: URI.t() | String.t()
```

# `default_options`

```elixir
@spec default_options() :: keyword()
```

Returns default options.

See `default_options/1` for more information.

# `default_options`

```elixir
@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

# `get_headers_list`
*since 0.5.10* 

```elixir
@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"}]

# `merge`

```elixir
@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"]}

# `new`

```elixir
@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_agent` becomes `"user-agent"`.

      * string header names are downcased.

      * `%DateTime{}` header values are encoded as "HTTP date".

    If you set `:headers` options both in `Req.new/1` and `request/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"](https://hexdocs.pm/elixir/IO.html#module-io-data).

      * `enumerable` - stream request body chunks emitted by the given `Enumerable`.

      * `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/4` and should
        return one of:

          * `{:data, chunk, acc}` - Emit request body `chunk` and continue streaming.

          * `{:done, chunk, acc}` - emit the final request body `chunk`. `acc` is passed to the
            response streaming function.

          * `{:done, acc}` - request body streaming is done. `acc` is 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}`
            from `Req.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 (via
    [`put_base_url`](`Req.Steps.put_base_url/1`) step.)

  * `:params` - if set, appends parameters to the request query string (via
    [`put_params`](`Req.Steps.put_params/1`) step.)

  * `:path_params` - if set, uses a templated request path (via
    [`put_path_params`](`Req.Steps.put_path_params/1`) step.)

  * `:path_params_style` (*available since v0.5.1*) - how path params are expressed (via
    [`put_path_params`](`Req.Steps.put_path_params/1`) step). Can be one of:

       * `:colon` - (default) for Plug-style parameters, such as `:code` in
         `https://httpbingo.org/status/:code`.

       * `:curly` - for [OpenAPI](https://swagger.io/specification/)-style parameters, such as
         `{code}` in `https://httpbingo.org/status/{code}`.

Authentication options:

  * `:auth` - sets request authentication (via `Req.Auth` step.)

    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 from `path`.

      * `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`](`Req.Steps.encode_body/1`)):

  * `:form` - if set, encodes the request body as `application/x-www-form-urlencoded`

  * `:form_multipart` - if set, encodes the request body as `multipart/form-data`.

  * `:json` - if set, encodes the request body as JSON

Other request body options:

  * `:compress_body` - if set to `true`, compresses the request body using gzip (via [`compress_body`](`Req.Steps.compress_body/1`) step.)
    Defaults to `false`.

Other request options:

  * `:user_agent` - sets the `user-agent` request header, see `Req.Steps.put_user_agent/1`.

  * `:range` - sets the `range` request header, see `Req.Steps.put_range/1`.

AWS Signature Version 4 options ([`put_aws_sigv4`](`Req.Steps.put_aws_sigv4/1`) 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 to `DateTime.utc_now(:second)`.

Response body options:

  * `:compressed` - if set to `true`, asks the server to return a compressed response and
    decompresses it. Defaults to `false`.

    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: true` for endpoints you trust.

  * `:raw` - if set to `true`, disables body decompression and automatic decoding
    (see `Req.Decompress` and `Req.Decode`). Defaults to `false`.

  * `:decode_body` - if set to `false`, disables automatic response body decoding.
    Defaults to `true`.

  * `:decoders` - the list of decoders to use for automatic response body decoding.
    Defaults to `[:json, :json_api, :ndjson, :sse]`. See `Req.Decode` for 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 the `response.body`
        field.

      * `collectable` - stream response body into a `t:Collectable.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.body` is set to opaque data structure `Req.Response.Async` which implements
        `Enumerable` that 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/4` or
        `into: collectable` instead.

    **Note**: `Req.stream/4` does not support `:into` option.

Response redirect options (`Req.Redirect` step):

  * `:redirect` - if set to `false`, disables automatic response redirects. Defaults to `true`.

  * `:redirect_trusted` - by default, authorization credentials are only sent on redirects
    with the same host, scheme and port. If `:redirect_trusted` is set to `true`, credentials
    will be sent to any host. Defaults to `false`.

  * `:redirect_log_level` - the log level to emit redirect logs at. Can also be set
    to `false` to disable logging these messages. Defaults to `:debug`.

  * `:max_redirects` - the maximum number of redirects, defaults to `10`.

Other response options:

  * `:expect` - the expected HTTP response status (via `Req.Expect` step).
    Can be an integer, a range, or a list of integers/ranges.

  * `:checksum` - if set, this is the expected response body checksum, see `Req.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.TransportError` with `reason: :timeout | :econnrefused | :closed`

          * `Req.HTTPError` with
            `protocol: :http2, reason: :unprocessed | :pool_not_available`

      * `:transient` - same as `:safe_transient` except retries all HTTP methods (POST, DELETE, etc.)

      * `fun` - a 2-arity function that accepts a `Req.Request` and either a `Req.Response` or an exception struct
        and returns one of the following:

          * `true` - retry using the default delay described under `:retry_delay` 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 of the `Retry-After` header 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_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 to `false` to disable
    logging these messages. Defaults to `:warning`.

  * `:max_retries` - maximum number of retry attempts, defaults to `3` (for a total of `4`
    requests to the server, including the initial one.)

Request adapters:

  * `:adapter` - adapter to use to make the actual HTTP request. See `:adapter` field description
    in the `Req.Request` module 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 the `Req.Plug` adapter).

    The plug can be one of:

      * A _function_ plug: a `fun(conn)` or `fun(conn, options)` function that takes a
        `Plug.Conn` and returns a `Plug.Conn`.

      * A _module_ plug: a `module` name or a `{module, options}` tuple.

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`. See
        `t:Finch.Request.build_opt/0` and `t:Finch.request_opt/0` for more information.

      * Finch pool options, e.g.: `:conn_max_idle_time`, `:pool_max_idle_time`, `:conn_opts`.
        See `Finch.start_link/1` for more information.

        Finch pool options cannot be mixed with `:name` option.

    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 (see `Mint.HTTP.connect/4` for options):

      * `:timeout` - socket connect timeout in milliseconds, defaults to `30_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 to `false`.

  * `:receive_timeout` - socket receive timeout in milliseconds, defaults to `15_000`.

  * `:request_timeout` - response timeout in milliseconds, defaults to `:infinity`.
    See `Finch.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 with `Finch.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

# `delete`

```elixir
@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:

  * an url (`String` or `URI`);

  * 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://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"

# `delete!`

```elixir
@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:

  * an url (`String` or `URI`);

  * a `Keyword` options;

  * a `Req.Request` struct

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"

# `get`

```elixir
@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:

  * an url (`String` or `URI`);

  * 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

# `get!`

```elixir
@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:

  * an url (`String` or `URI`);

  * 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

# `head`

```elixir
@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:

  * an url (`String` or `URI`);

  * 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://httpbingo.org/status/201")
    iex> resp.status
    201

With options:

    iex> {:ok, resp} = Req.head(url: "https://httpbingo.org/status/201")
    iex> resp.status
    201

With request struct:

    iex> req = Req.new(base_url: "https://httpbingo.org")
    iex> {:ok, resp} = Req.head(req, url: "/status/201")
    iex> resp.status
    201

# `head!`

```elixir
@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:

  * an url (`String` or `URI`);

  * a `Keyword` options;

  * a `Req.Request` struct

See `new/1` for a list of available options.

## Examples

With URL:

    iex> Req.head!("https://httpbingo.org/status/201").status
    201

With options:

    iex> Req.head!(url: "https://httpbingo.org/status/201").status
    201

With request struct:

    iex> req = Req.new(base_url: "https://httpbingo.org")
    iex> Req.head!(req, url: "/status/201").status
    201

# `patch`

```elixir
@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:

  * an url (`String` or `URI`);

  * 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://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!"

# `patch!`

```elixir
@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:

  * an url (`String` or `URI`);

  * a `Keyword` options;

  * a `Req.Request` struct

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!"

# `post`

```elixir
@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:

  * an url (`String` or `URI`);

  * 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://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!"

# `post!`

```elixir
@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:

  * an url (`String` or `URI`);

  * a `Keyword` options;

  * a `Req.Request` struct

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!"

# `put`

```elixir
@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:

  * an url (`String` or `URI`);

  * 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://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!"

# `put!`

```elixir
@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:

  * an url (`String` or `URI`);

  * a `Keyword` options;

  * a `Req.Request` struct

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!"

# `request`

```elixir
@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

# `request!`

```elixir
@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

# `stream`

```elixir
@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 -&gt; {:cont, acc} | {:halt, acc}),
     options: keyword()
```

Streams an HTTP request.

`req` can be one of:

  * an url (`String` or `URI`);
  * a `Keyword` options;
  * a `Req.Request` struct

`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}
    end

`data` 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"

# `cancel_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

# `parse_message`

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`](`c:GenServer.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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
