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

A collection of built-in steps.

Req is composed of:

  * `Req` - the high-level API

  * `Req.Request` - the low-level API and the request struct

  * `Req.Auth`, …, `Req.Steps` - a collection of built-in steps (you're here!)

  * `Req.Test` - the testing conveniences

See also step modules:

  * `Req.Auth`

  * `Req.Checksum`

  * `Req.Decode`

  * `Req.Decompress`

  * `Req.Expect`

  * `Req.Redirect`

  * `Req.Retry`

# `compress_body`

Compresses the request body.

Not supported with `body: req_body_fun`.

## Request Options

  * `:compress_body` - if set to `true`, compresses the request body using gzip.
    Defaults to `false`.

# `encode_body`

Encodes the request body.

## Request Options

  * `:form` - if set, encodes the request body as `application/x-www-form-urlencoded`
    (using `URI.encode_query/1`).

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

    It accepts `name` / `value` pairs. `value` can be one of:

      * integer (automatically encoded as string)

      * iodata

      * `File.Stream`

      * `Enumerable`

      * `{value, options}` tuple.

         `value` can be any of the values mentioned above.

         Supported options are: `:filename`, `:content_type`, and `:size`.

         When `value` is an `Enumerable`, option `:size` can be set with
         the binary size of the `value`. The size will be used to calculate
         and send the `content-length` header which might be required for
         some servers. There is no need to pass `:size` for `integer`,
         `iodata`, and `File.Stream` values as it's automatically calculated.

  * `:json` - if set, encodes the request body as JSON (using `JSON.encode_to_iodata!/1`), sets
    the `accept` header to `application/json`, and the `content-type` header to `application/json`.

When the request has the default HTTP method, GET, and the request body is set, this step
automatically changes HTTP method to POST.

## Examples

Encoding form (`application/x-www-form-urlencoded`):

    iex> Req.post!("https://httpbingo.org/anything", form: [a: 1]).body["form"]
    %{"a" => ["1"]}

Encoding form (`multipart/form-data`):

    iex> fields = [a: 1, b: {"2", filename: "b.txt"}]
    iex> resp = Req.post!("https://httpbingo.org/anything", form_multipart: fields)
    iex> resp.body["form"]
    %{"a" => ["1"]}
    iex> resp.body["files"]
    %{"b" => ["2"]}

Encoding streaming form (`multipart/form-data`):

    iex> stream = Stream.cycle(["abc"]) |> Stream.take(3)
    iex> fields = [file: {stream, filename: "b.txt"}]
    iex> resp = Req.post!("https://httpbingo.org/anything", form_multipart: fields)
    iex> resp.body["files"]
    %{"file" => ["abcabcabc"]}

    # with explicit :size
    iex> stream = Stream.cycle(["abc"]) |> Stream.take(3)
    iex> fields = [file: {stream, filename: "b.txt", size: 9}]
    iex> resp = Req.post!("https://httpbingo.org/anything", form_multipart: fields)
    iex> resp.body["files"]
    %{"file" => ["abcabcabc"]}

Encoding JSON:

    iex> Req.post!("https://httpbingo.org/post", json: %{a: 1}).body["json"]
    %{"a" => 1}

Automatically change GET to POST when body is set:

    iex> Req.request!("https://httpbingo.org/post", json: %{a: 1}).body["json"]
    %{"a" => 1}

# `put_aws_sigv4`

Signs request with AWS Signature Version 4.

## Request Options

  * `: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.

      * `:token` - if set, the AWS security token, for example returned from AWS STS.

      * `:service` - the AWS service. We try to automatically detect the service (e.g.
        `s3.amazonaws.com` host sets service to `:s3`)

      * `:region` - the AWS region. Defaults to `"us-east-1"`.

      * `:datetime` - the request datetime, defaults to `DateTime.utc_now(:second)`.

    Additionally, it can be an `{mod, fun, args}` tuple that returns the above
    options.

## Examples

    iex> req =
    ...>   Req.new(
    ...>     base_url: "https://s3.amazonaws.com",
    ...>     aws_sigv4: [
    ...>       access_key_id: System.get_env("AWS_ACCESS_KEY_ID"),
    ...>       secret_access_key: System.get_env("AWS_SECRET_ACCESS_KEY")
    ...>     ]
    ...>   )
    iex>
    iex> %{status: 200} = Req.put!(req, url: "/bucket1/key1", body: "Hello, World!")
    iex> resp = Req.get!(req, url: "/bucket1/key1").body
    "Hello, World!"

Request body streaming also works though `content-length` header must be explicitly set:

    iex> path = "a.txt"
    iex> File.write!(path, String.duplicate("a", 100_000))
    iex> size = File.stat!(path).size
    iex> chunk_size = 10 * 1024
    iex> stream = File.stream!(path, chunk_size)
    iex> %{status: 200} = Req.put!(req, url: "/bucket1/key1", headers: [content_length: size], body: stream)
    iex> byte_size(Req.get!(req, url: "/bucket1/key1").body)
    100_000

# `put_base_url`

Sets base URL for all requests.

## Request Options

  * `:base_url` - if set, the request URL is merged with this base URL.

    The base url can be a string, a `%URI{}` struct, a 0-arity function,
    or a `{mod, fun, args}` tuple describing a function to call.

## Examples

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

# `put_params`

Adds params to request query string.

## Request Options

  * `:params` - params to add to the request query string. Defaults to `[]`.

## Examples

    iex> Req.get!("https://httpbingo.org/anything/query", params: [x: 1, y: 2]).body["args"]
    %{"x" => ["1"], "y" => ["2"]}

# `put_path_params`

Uses a templated request path.

By default, params in the URL path are expressed as strings prefixed with `:`. For example,
`:code` in `https://httpbingo.org/status/:code`. If you want to use the `{code}` syntax,
set `path_params_style: :curly`. Param names must start with a letter and can contain letters,
digits, and underscores; this is true both for `:colon_params` as well as `{curly_params}`.

Path params are replaced in the request URL path. The path params are specified as a keyword
list of parameter names and values, as in the examples below. The values of the parameters are
converted to strings using the `String.Chars` protocol (`to_string/1`).

## Request Options

  * `:path_params` - if set, params to add to the templated path. Defaults to `nil`.

  * `:path_params_style` (*available since v0.5.1*) - how path params are expressed. 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}`.

## Examples

    iex> Req.get!("https://httpbingo.org/status/:code", path_params: [code: 201]).status
    201

    iex> Req.get!("https://httpbingo.org/status/{code}", path_params: [code: 201], path_params_style: :curly).status
    201

# `put_range`

Sets the "Range" request header.

## Request Options

  * `:range` - can be one of the following:

      * a string - returned as is

      * a `first..last` range - converted to `"bytes=<first>-<last>"`

## Examples

    iex> response = Req.get!("https://httpbingo.org/range/100", range: 0..3)
    iex> response.status
    206
    iex> response.body
    "abcd"
    iex> Req.Response.get_header(response, "content-range")
    ["bytes 0-3/100"]

# `put_user_agent`

Sets the user-agent header.

## Request Options

  * `:user_agent` - sets the `user-agent` header. Defaults to `"req/0.8.0-rc.0"`.

## Examples

    iex> Req.get!("https://httpbingo.org/user-agent").body
    %{"user-agent" => "req/0.8.0-rc.0"}

    iex> Req.get!("https://httpbingo.org/user-agent", user_agent: "foo").body
    %{"user-agent" => "foo"}

---

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