Skip to content

Commit

Permalink
Prepare for v0.4.9
Browse files Browse the repository at this point in the history
  • Loading branch information
wojtekmach committed Feb 14, 2024
1 parent f93d84b commit bfabe15
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 13 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# CHANGELOG

## v0.4.9 (2024-02-14)

* [`retry`]: Raise on invalid return from `:retry_delay` function

* [`run_finch`]: Update to Finch 0.17

* [`run_finch`]: Deprecate `connect_options: [protocol: ...]` in favour of
`connect_options: [protocols: ...]]` which defaults to `[:http1, :http2]`, that is,
make request using HTTP/1 but if negotiated switch to HTTP/2 over the HTTP/1 connection.

* New step: [`put_aws_sigv4`] - signs request with AWS Signature Version 4.

## v0.4.8 (2023-12-11)

* [`put_plug`]: Fix response streaming. Previously we were relying on unreleased
Expand Down Expand Up @@ -782,6 +794,7 @@ See "Adapter" section in `Req.Request` module documentation for more information
[`retry`]: https://hexdocs.pm/req/Req.Steps.html#retry/1
[`run_finch`]: https://hexdocs.pm/req/Req.Steps.html#run_finch/1
[`checksum`]: https://hexdocs.pm/req/Req.Steps.html#checksum/1
[`put_aws_sigv4`]: https://hexdocs.pm/req/Req.Steps.html#put_aws_sigv4/1

[`Req.new/1`]: https://hexdocs.pm/req/Req.html#new/1
[`Req.request/2`]: https://hexdocs.pm/req/Req.html#request/2
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ write new ones.

* Range requests (via [`put_range`]) step.)

* Use AWS V4 Signature (via [`put_aws_sigv4`]) step.)

* Request body streaming (by setting `body: enumerable`.)

* Response body streaming (by setting `into: fun | collectable`.)
Expand Down Expand Up @@ -256,6 +258,7 @@ limitations under the License.
[`retry`]: https://hexdocs.pm/req/Req.Steps.html#retry/1
[`run_finch`]: https://hexdocs.pm/req/Req.Steps.html#run_finch/1
[`checksum`]: https://hexdocs.pm/req/Req.Steps.html#checksum/1
[`put_aws_sigv4`]: https://hexdocs.pm/req/Req.Steps.html#put_aws_sigv4/1

[Finch]: https://github.com/sneako/finch
[cURL]: https://curl.se
Expand Down
16 changes: 16 additions & 0 deletions lib/req.ex
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,22 @@ defmodule Req do
* `:compress_body` - if set to `true`, compresses the request body using gzip (via [`compress_body`](`Req.Steps.compress_body/1`) step.)
Defaults to `false`.
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"`.
This functionality requires [`:aws_signature`](https://hex.pm/packages/aws_signature) dependency:
{:aws_signature, "~> 0.3.0"}
Response body options:
* `:compressed` - if set to `true`, asks the server to return compressed response.
Expand Down
48 changes: 44 additions & 4 deletions lib/req/steps.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1301,8 +1301,43 @@ defmodule Req.Steps do
Code.ensure_loaded?(:aws_signature)
end

# experimental
@doc false
@doc """
Signs request with AWS Signature Version 4.
This step requires [`:aws_signature`](https://hex.pm/packages/aws_signature) dependency:
{:aws_signature, "~> 0.3.0"}
## 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.
* `:service` - the AWS service.
* `:region` - if set, AWS region. Defaults to `"us-east-1"`.
## 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"),
...> service: :s3
...> ]
...> )
iex>
iex> %{status: 200} = Req.put!(req, "/bucket1/key1", body: "Hello, World!")
iex> resp = Req.get!(req, "/bucket1/key1").body
"Hello, World!"
"""
@doc step: :request
def put_aws_sigv4(request) do
if aws_options = request.options[:aws_sigv4] do
unless aws_signature_loaded?() do
Expand Down Expand Up @@ -1346,8 +1381,13 @@ defmodule Req.Steps do
region = Keyword.get(aws_options, :region, "us-east-1")

now = NaiveDateTime.utc_now() |> NaiveDateTime.to_erl()
body = IO.iodata_to_binary(request.body || "")

request =
request
|> Req.Request.put_new_header("host", request.url.host)
|> Req.Request.put_new_header("content-length", to_string(byte_size(body)))

request = Req.Request.put_new_header(request, "host", request.url.host)
headers = for {name, values} <- request.headers, value <- values, do: {name, value}

headers =
Expand All @@ -1360,7 +1400,7 @@ defmodule Req.Steps do
to_string(request.method),
to_string(request.url),
headers,
IO.iodata_to_binary(request.body || "")
body
)

Req.update(request, headers: headers)
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Req.MixProject do
use Mix.Project

@version "0.4.8"
@version "0.4.9"
@source_url "https://github.com/wojtekmach/req"

def project do
Expand Down
41 changes: 33 additions & 8 deletions test/req/integration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ defmodule Req.IntegrationTest do

@moduletag :integration

setup do
original_gl = Process.group_leader()
{:ok, capture_gl} = StringIO.open("")
Process.group_leader(self(), capture_gl)

on_exit(fn ->
Process.group_leader(self(), original_gl)
end)
setup context do
if context[:doctest] do
original_gl = Process.group_leader()
{:ok, capture_gl} = StringIO.open("")
Process.group_leader(self(), capture_gl)

on_exit(fn ->
Process.group_leader(self(), original_gl)
end)
else
:ok
end
end

doctest Req,
Expand Down Expand Up @@ -38,4 +42,25 @@ defmodule Req.IntegrationTest do
decompress_body: 1,
handle_http_errors: 1
]

@aws_access_key_id System.get_env("REQ_AWS_ACCESS_KEY_ID")
@aws_secret_access_key System.get_env("REQ_AWS_SECRET_ACCESS_KEY")
@aws_bucket System.get_env("REQ_AWS_BUCKET")

@tag :s3
test "s3" do
req =
Req.new(
base_url: "https://#{@aws_bucket}.s3.amazonaws.com",
aws_sigv4: [
access_key_id: @aws_access_key_id,
secret_access_key: @aws_secret_access_key,
service: :s3
]
)

now = to_string(DateTime.utc_now())
%{status: 200} = Req.put!(req, url: "/key1", json: %{now: now})
assert Req.get!(req, url: "/key1").body == %{"now" => now}
end
end

0 comments on commit bfabe15

Please sign in to comment.