Skip to content

Commit

Permalink
Add put_path_params_style/2 step
Browse files Browse the repository at this point in the history
  • Loading branch information
whatyouhide committed Jun 19, 2024
1 parent 2444dee commit 910c447
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
9 changes: 9 additions & 0 deletions lib/req.ex
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ defmodule Req do
* `:path_params` - if set, uses a templated request path (via
[`put_path_params`](`Req.Steps.put_path_params/1`) step.)
* `:path_params_style` - configures how `:path_params` are expressed (via
[`put_path_params_style`](`Req.Steps.put_path_params_style/1`) step). Can be one of:
* `:colon` - default, params are expressed as `:name` in the path.
* `:curly` - uses [OpenAPI](https://swagger.io/specification/)-style `{name}` parameters.
*Available since v0.5.1*.
Authentication options:
* `:auth` - sets request authentication (via [`auth`](`Req.Steps.auth/1`) step.)
Expand Down
38 changes: 32 additions & 6 deletions lib/req/steps.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ defmodule Req.Steps do
:base_url,
:params,
:path_params,
:path_params_style,
:auth,
:form,
:json,
Expand Down Expand Up @@ -71,6 +72,7 @@ defmodule Req.Steps do
put_base_url: &Req.Steps.put_base_url/1,
auth: &Req.Steps.auth/1,
put_params: &Req.Steps.put_params/1,
put_path_params_style: &Req.Steps.put_path_params_style/1,
put_path_params: &Req.Steps.put_path_params/1,
put_range: &Req.Steps.put_range/1,
cache: &Req.Steps.cache/1,
Expand Down Expand Up @@ -398,6 +400,14 @@ defmodule Req.Steps do
@doc """
Uses a templated request path.
By default, params in the URL path are expressed as strings prefixed with `:`. For example,
`:code` in `https://httpbin.org/status/:code`. If you want to use the `{code}` syntax,
set `path_params_style: :curly` (see `put_path_params_style/1`).
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` - params to add to the templated path. Defaults to `[]`.
Expand All @@ -424,23 +434,39 @@ defmodule Req.Steps do
end

defp apply_path_params(request, params) do
regex =
case Req.Request.get_private(request, :path_params_style) || raise("missing") do
:colon -> ~r/:([a-zA-Z]{1}[\w_]*)/
:curly -> ~r/\{([a-zA-Z]{1}[\w_]*)\}/
end

update_in(request.url.path, fn
nil ->
nil

path ->
Regex.replace(~r/:([a-zA-Z]{1}[\w_]*)/, path, fn match, key ->
Regex.replace(regex, path, fn match, key ->
case params[String.to_existing_atom(key)] do
nil ->
match

value ->
value |> to_string() |> URI.encode()
nil -> match
value -> value |> to_string() |> URI.encode()
end
end)
end)
end

@doc """
TODO
"""
@doc since: "0.5.1"
@doc step: :request
def put_path_params_style(request) do
Req.Request.put_private(
request,
:path_params_style,
Req.Request.get_option(request, :path_params_style, :colon)
)
end

@doc """
Adds params to request query string.
Expand Down
16 changes: 13 additions & 3 deletions test/req/steps_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,18 @@ defmodule Req.StepsTest do
end

test "put_path_params" do
req = Req.new(url: "http://foo/:id", path_params: [id: "abc|def"]) |> Req.Request.prepare()
assert URI.to_string(req.url) == "http://foo/abc%7Cdef"
req =
Req.new(url: "http://foo/:id{ola}", path_params: [id: "abc|def"]) |> Req.Request.prepare()

assert URI.to_string(req.url) == "http://foo/abc%7Cdef{ola}"
end

test "put_path_params_style" do
req =
Req.new(url: "http://foo/{id}:bar", path_params: [id: "abc|def"], path_params_style: :curly)
|> Req.Request.prepare()

assert URI.to_string(req.url) == "http://foo/abc%7Cdef:bar"
end

test "put_range" do
Expand Down Expand Up @@ -1138,7 +1148,7 @@ defmodule Req.StepsTest do
assert_receive :ping
refute_receive _

assert req.private == %{req_redirect_count: 3}
assert %{req_redirect_count: 3} = req.private
assert Exception.message(e) == "too many redirects (3)"
end

Expand Down

0 comments on commit 910c447

Please sign in to comment.