-module(dream_http_client@stream). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/dream_http_client/stream.gleam"). -export([stream_request/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Streaming HTTP request functionality\n" "\n" " This module provides streaming HTTP request functionality that returns\n" " a yielder of response chunks as they arrive. Use this for:\n" "\n" " - Large file downloads\n" " - Streaming AI responses\n" " - Real-time data feeds\n" " - Any case where you want to process data incrementally\n" "\n" " ## Quick Start\n" "\n" " ```gleam\n" " import dream_http_client/client\n" " import dream_http_client/stream\n" " import gleam/yielder\n" "\n" " client.new\n" " |> client.host(\"cdn.example.com\")\n" " |> client.path(\"/large-file.zip\")\n" " |> stream.stream_request()\n" " |> yielder.each(fn(chunk) {\n" " // Process each chunk as it arrives\n" " save_chunk(chunk)\n" " })\n" " ```\n" "\n" " ## Processing Streams\n" "\n" " The yielder can be consumed with `yielder.each()`, `yielder.to_list()`, or\n" " other yielder functions. Each chunk is a `BytesTree` that you can convert\n" " to a string or process as binary data.\n" ). -file("src/dream_http_client/stream.gleam", 46). ?DOC( " Convert a ClientRequest to a gleam/http/request.Request\n" "\n" " Internal helper function that converts the builder-style ClientRequest\n" " to the standard gleam/http Request type.\n" ). -spec to_http_request(dream_http_client@client:client_request()) -> gleam@http@request:request(binary()). to_http_request(Client_request) -> {request, erlang:element(2, Client_request), erlang:element(8, Client_request), erlang:element(9, Client_request), erlang:element(3, Client_request), erlang:element(4, Client_request), erlang:element(5, Client_request), erlang:element(6, Client_request), erlang:element(7, Client_request)}. -file("src/dream_http_client/stream.gleam", 102). ?DOC( " Create a yielder that streams HTTP response chunks\n" "\n" " Sends an HTTP request and returns a yielder that produces chunks of the\n" " response body as they arrive from the server. This allows you to process\n" " large responses incrementally without loading the entire response into memory.\n" "\n" " The yielder produces `Next(chunk, new_state)` for each chunk until the stream\n" " completes, then produces `Done`.\n" "\n" " ## Parameters\n" "\n" " - `req`: The configured HTTP request\n" "\n" " ## Returns\n" "\n" " A `Yielder` that produces `BytesTree` chunks. Use `yielder.each()` to process\n" " chunks, or `yielder.to_list()` to collect all chunks.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream_http_client/client\n" " import dream_http_client/stream\n" " import gleam/yielder\n" " import gleam/bytes_tree\n" "\n" " // Stream and process chunks\n" " client.new\n" " |> client.host(\"api.example.com\")\n" " |> client.path(\"/stream\")\n" " |> stream.stream_request()\n" " |> yielder.each(fn(chunk) {\n" " let body = bytes_tree.to_string(chunk)\n" " process_chunk(body)\n" " })\n" "\n" " // Or collect all chunks\n" " let chunks = client.new\n" " |> client.host(\"cdn.example.com\")\n" " |> client.path(\"/file.zip\")\n" " |> stream.stream_request()\n" " |> yielder.to_list()\n" " ```\n" ). -spec stream_request(dream_http_client@client:client_request()) -> gleam@yielder:yielder(gleam@bytes_tree:bytes_tree()). stream_request(Req) -> Http_req = to_http_request(Req), gleam@yielder:unfold(none, fun(State) -> case State of none -> Request_result = dream_http_client@internal:start_httpc_stream( Http_req ), Owner = dream_http_client@internal:extract_owner_pid( Request_result ), case dream_http_client@internal:receive_next(Owner) of {ok, Bin} -> {next, gleam@bytes_tree:from_bit_array(Bin), {some, Owner}}; {error, _} -> done end; {some, Owner@1} -> case dream_http_client@internal:receive_next(Owner@1) of {ok, Bin@1} -> {next, gleam@bytes_tree:from_bit_array(Bin@1), {some, Owner@1}}; {error, _} -> done end end end).