Skip to content

Commit

Permalink
Polish up Req.Request docs (#366)
Browse files Browse the repository at this point in the history
  • Loading branch information
whatyouhide authored Jun 1, 2024
1 parent 357f27a commit be9e8ce
Showing 1 changed file with 69 additions and 22 deletions.
91 changes: 69 additions & 22 deletions lib/req/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -122,45 +122,51 @@ defmodule Req.Request do
Nothing is actually executed until we run the pipeline with `Req.Request.run_request/1`.
### Request steps
### Request Steps
A request step is a function that accepts a `request` and returns one of the following:
A **request step** is a function that accepts a `request` and returns one of the following:
* A `request`
* A `request`.
* A `{request, response_or_error}` tuple. In that case no further request steps are executed
and the return value goes through response or error steps
* A `{request, response_or_error}` tuple. In this case no further request steps are executed
and the return value goes through response or error steps.
Examples:
#### Examples
A request step that adds a `user-agent` header if it's not there already:
def put_default_headers(request) do
update_in(request.headers, &[{"user-agent", "req"} | &1])
Req.Request.put_new_header(request, "user-agent", "req")
end
The next is a request step that reads the response from cache if available. Note how, if the
cached response is available, this step returns a `{request, response}` tuple so that the
request doesn't actually go through:
def read_from_cache(request) do
case ResponseCache.fetch(request) do
{:ok, response} -> {request, response}
:error -> request
end
end
### Response and error steps
### Response and Error Steps
A response step is a function that accepts a `{request, response}` tuple and returns one of the
following:
* A `{request, response}` tuple
* A `{request, response}` tuple.
* A `{request, exception}` tuple. In that case, no further response steps are executed but the
exception goes through error steps
exception goes through error steps.
Similarly, an error step is a function that accepts a `{request, exception}` tuple and returns one
of the following:
* A `{request, exception}` tuple
* A `{request, response}` tuple. In that case, no further error steps are executed but the
response goes through response steps
response goes through response steps.
Examples:
Expand All @@ -181,7 +187,7 @@ defmodule Req.Request do
### Halting
Any step can call `halt/2` to halt the pipeline. This will prevent any further steps
Any step can call `halt/2` to halt the pipeline. This prevents any further steps
from being invoked.
Examples:
Expand All @@ -207,6 +213,7 @@ defmodule Req.Request do
## Request Options
* `:print_headers` - if `true`, prints the headers. Defaults to `false`.
\"""
def attach(%Req.Request{} = request, options \\ []) do
request
Expand Down Expand Up @@ -283,7 +290,7 @@ defmodule Req.Request do
## Adapter
As noted in the ["Request steps"](#module-request-steps) section, a request step besides returning the request,
As noted in the ["Request Steps"](#module-request-steps) section, a request step besides returning the request,
might also return `{request, response}` or `{request, exception}`, thus invoking either response or error steps next.
This is exactly how Req makes the underlying HTTP call, by invoking a request step that follows this contract.
Expand Down Expand Up @@ -335,8 +342,12 @@ defmodule Req.Request do
Req.get!("https://api.github.com/repos/wojtekmach/req", adapter: hackney).body["description"]
#=> "Req is a batteries-included HTTP client for Elixir."
"""

@typedoc """
The request struct.
"""
@type t() :: %Req.Request{
method: atom(),
url: URI.t(),
Expand Down Expand Up @@ -402,8 +413,11 @@ defmodule Req.Request do
iex> resp.status
200
"""
@spec new(keyword()) :: t()
def new(options \\ [])

if Req.MixProject.legacy_headers_as_lists?() do
def new(options \\ []) do
def new(options) do
options =
options
|> Keyword.validate!([:method, :url, :headers, :body, :adapter, :options])
Expand All @@ -413,7 +427,7 @@ defmodule Req.Request do
struct!(__MODULE__, options)
end
else
def new(options \\ []) do
def new(options) do
options =
options
|> Keyword.validate!([:method, :url, :headers, :body, :adapter, :options])
Expand Down Expand Up @@ -556,6 +570,7 @@ defmodule Req.Request do
@doc """
Gets the value for a specific private `key`.
"""
@spec get_private(t(), atom(), default) :: term() | default when default: var
def get_private(request, key, default \\ nil) when is_atom(key) do
Map.get(request.private, key, default)
end
Expand All @@ -575,14 +590,15 @@ defmodule Req.Request do
iex> Req.Request.update_private(req, :b, 11, & &1 + 1).private
%{a: 1, b: 11}
"""
@spec update_private(t(), key :: atom(), default :: term(), (atom() -> term())) :: t()
@spec update_private(t(), key :: atom(), default :: term(), (term() -> term())) :: t()
def update_private(request, key, default, fun) when is_atom(key) and is_function(fun, 1) do
update_in(request.private, &Map.update(&1, key, default, fun))
end

@doc """
Assigns a private `key` to `value`.
"""
@spec put_private(t(), atom(), term()) :: t()
def put_private(request, key, value) when is_atom(key) do
put_in(request.private[key], value)
end
Expand All @@ -599,6 +615,8 @@ defmodule Req.Request do
This function returns an updated request and the response or exception that caused the halt.
It's perfect when used in a request step to stop the pipeline.
See the ["Halting"](#module-halting) section in the module documentation for more information.
## Examples
Req.Request.prepend_request_steps(request, circuit_breaker: fn request ->
Expand All @@ -623,7 +641,10 @@ defmodule Req.Request do
end

@doc """
Appends request steps.
Appends **request steps** to the existing request steps.
See the ["Request Steps"](#module-request-steps) section in the module documentation
for more information.
## Examples
Expand All @@ -632,6 +653,7 @@ defmodule Req.Request do
inspect: &IO.inspect/1
)
"""
@spec append_request_steps(t(), keyword(fun())) :: t()
def append_request_steps(request, steps) do
%{
request
Expand All @@ -641,7 +663,10 @@ defmodule Req.Request do
end

@doc """
Prepends request steps.
Prepends **request steps** to the existing request steps.
See the ["Request Steps"](#module-request-steps) section in the module documentation
for more information.
## Examples
Expand All @@ -650,6 +675,7 @@ defmodule Req.Request do
inspect: &IO.inspect/1
)
"""
@spec prepend_request_steps(t(), keyword(fun())) :: t()
def prepend_request_steps(request, steps) do
%{
request
Expand All @@ -659,7 +685,10 @@ defmodule Req.Request do
end

@doc """
Appends response steps.
Appends **response steps** to the existing response steps.
See the ["Response and Error Steps"](#module-response-and-error-steps) section in the
module documentation for more information.
## Examples
Expand All @@ -668,6 +697,7 @@ defmodule Req.Request do
inspect: &IO.inspect/1
)
"""
@spec append_response_steps(t(), keyword(fun())) :: t()
def append_response_steps(request, steps) do
%{
request
Expand All @@ -676,7 +706,10 @@ defmodule Req.Request do
end

@doc """
Prepends response steps.
Prepends **response steps** to the existing response steps.
See the ["Response and Error Steps"](#module-response-and-error-steps) section in the
module documentation for more information.
## Examples
Expand All @@ -685,6 +718,7 @@ defmodule Req.Request do
inspect: &IO.inspect/1
)
"""
@spec prepend_response_steps(t(), keyword(fun())) :: t()
def prepend_response_steps(request, steps) do
%{
request
Expand All @@ -693,7 +727,10 @@ defmodule Req.Request do
end

@doc """
Appends error steps.
Appends **error steps** to the existing error steps.
See the ["Response and Error Steps"](#module-response-and-error-steps) section in the
module documentation for more information.
## Examples
Expand All @@ -702,6 +739,7 @@ defmodule Req.Request do
inspect: &IO.inspect/1
)
"""
@spec append_error_steps(t(), keyword(fun())) :: t()
def append_error_steps(request, steps) do
%{
request
Expand All @@ -710,7 +748,10 @@ defmodule Req.Request do
end

@doc """
Prepends error steps.
Prepends **error steps** to the existing error steps.
See the ["Response and Error Steps"](#module-response-and-error-steps) section in the
module documentation for more information.
## Examples
Expand All @@ -719,6 +760,7 @@ defmodule Req.Request do
inspect: &IO.inspect/1
)
"""
@spec prepend_error_steps(t(), keyword(fun())) :: t()
def prepend_error_steps(request, steps) do
%{
request
Expand Down Expand Up @@ -915,6 +957,9 @@ defmodule Req.Request do
[]
"""
@spec delete_header(t(), binary()) :: t()
def delete_header(request, name)

if Req.MixProject.legacy_headers_as_lists?() do
def delete_header(%Req.Request{} = request, name) when is_binary(name) do
name = Req.__ensure_header_downcase__(name)
Expand Down Expand Up @@ -949,6 +994,7 @@ defmodule Req.Request do
Req.get!(req, url: "/status/201", foo: :bar).status
#=> 201
"""
@spec register_options(t(), keyword()) :: t()
def register_options(%Req.Request{} = request, options) when is_list(options) do
update_in(request.registered_options, &MapSet.union(&1, MapSet.new(options)))
end
Expand Down Expand Up @@ -989,6 +1035,7 @@ defmodule Req.Request do
iex> response.status
200
"""
@spec run_request(t()) :: {t(), Req.Response.t() | Exception.t()}
def run_request(request)

def run_request(%{current_request_steps: [step | rest]} = request) do
Expand Down

0 comments on commit be9e8ce

Please sign in to comment.