From 90f784cfb54a087d66482871304e610ca1ed1175 Mon Sep 17 00:00:00 2001 From: Wojtek Mach Date: Sun, 27 Aug 2023 11:28:38 +0200 Subject: [PATCH] Update docs --- CHANGELOG.md | 50 +++++++++++++++++++++++++++++++++++--------------- README.md | 6 +++--- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaaaa5c1..763816b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,43 +57,61 @@ This legacy fallback will be removed on Req 1.0. ### Add Request Streaming Req v0.4 adds official support for request streaming by setting the request -body to a `{:stream, enumerable}` tuple. Here's an example: +body to an `enumerable`. Here's an example: ```elixir iex> stream = Stream.duplicate("foo", 3) -iex> Req.post!("https://httpbin.org/post", body: {:stream, stream}).body["data"] +iex> Req.post!("https://httpbin.org/post", body: stream).body["data"] "foofoofoo" ``` The enumerable is passed through request steps and they may change it. For example, -the [`compress_body`] step compressed the body on the fly. +the [`compress_body`] step gzips the request body on the fly. ### Add Response Streaming +Req v0.4 also adds response body streaming, via the `:into` option. + +Here's an example where we download the first 20kb (by making a _range_ request, via the +[`put_range`] step) of Elixir release zip. We stream the response bode into a function +and can inspect each chunk. The function receives a `{:data, data}, {req, resp}` and returns +a `{:cont | :halt, {req, resp}}` tuple. + ```elixir resp = Req.get!( url: "https://github.com/elixir-lang/elixir/releases/download/v1.15.4/elixir-otp-26.zip", - range: 0..100_000, - stream: fn {:data, data}, acc -> + range: 0..20_000, + into: fn {:data, data}, acc -> IO.inspect(byte_size(data), label: :chunk) {:cont, acc} end ) -# outputs: -# 17:07:38.131 [debug] redirecting to https://objects.githubusercontent.com/github-production-release-asset-2e6(...) -# chunk: 16384 -# chunk: 3617 +# output: 17:07:38.131 [debug] redirecting to https://objects.githubusercontent.com/github-production-release-asset-2e6(...) +# output: chunk: 16384 +# output: chunk: 3617 -resp.status -#=> 206 +resp.status #=> 206 +resp.headers["content-range"] #=> ["bytes 0-20000/6801977"] +resp.body #=> "" +``` -resp.headers["content-range"] -#=> ["bytes 0-20000/6801977"] +As the name `:into` implies, we an also stream response body into any [`Collectable`]. +Here's a similar snippet to above where we stream to a file: -resp.body -#=> "" +```elixir +resp = + Req.get!( + url: "https://github.com/elixir-lang/elixir/releases/download/v1.15.4/elixir-otp-26.zip", + range: 0..20_000, + into: File.stream!("elixit-otp-26.zip.1") + ) + +# output: 17:07:38.131 [debug] redirecting to (...) +resp.status #=> 206 +resp.headers["content-range"] #=> ["bytes 0-20000/6801977"] +resp.body #=> %File.Stream{} ``` ### Full CHANGELOG @@ -660,6 +678,7 @@ See "Adapter" section in `Req.Request` module documentation for more information [`put_path_params`]: https://hexdocs.pm/req/Req.Steps.html#put_path_params/1 [`put_plug`]: https://hexdocs.pm/req/Req.Steps.html#put_plug/1 [`put_user_agent`]: https://hexdocs.pm/req/Req.Steps.html#put_user_agent/1 +[`put_range`]: https://hexdocs.pm/req/Req.Steps.html#put_range/1 [`retry`]: https://hexdocs.pm/req/Req.Steps.html#retry/1 [`run_finch`]: https://hexdocs.pm/req/Req.Steps.html#run_finch/1 [`Req.request/2`]: https://hexdocs.pm/req/Req.html#request/2 @@ -673,3 +692,4 @@ See "Adapter" section in `Req.Request` module documentation for more information [`Req.Request.delete_option/2`]: https://hexdocs.pm/req/Req.Request.html#delete_option/2 [`Req.Response.get_header/2`]: https://hexdocs.pm/req/Req.Response.html#get_response/2 [`Req.Steps`]: https://hexdocs.pm/req/Req.Steps.html +[`Collectable`]: https://hexdocs.pm/elixir/Collectable.html diff --git a/README.md b/README.md index a150c015..857fa270 100644 --- a/README.md +++ b/README.md @@ -32,15 +32,15 @@ write new ones. * Request body encoding and automatic response body decoding (via [`encode_body`] and [`decode_body`] steps.) - * Request body streaming - * Encode params as query string (via [`put_params`] step.) * Basic, bearer, and `.netrc` authentication (via [`auth`] step.) * Range requests (via [`put_range`]) step.) - * Response streaming + * Request body streaming (by setting `body: enumerable`.) + + * Response body streaming (by setting `into: fun | collectable`.) * Follows redirects (via [`follow_redirects`] step.)