-module(aws@internal@http_streaming).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aws/internal/http_streaming.gleam").
-export([default_send/1, default_send_http2/1, with_timeout_and_tls/2, with_timeout_tls_http2/2]).
-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 send for the SDK runtime. Sits between the\n"
" generated service code and the Erlang FFI in `aws_streaming_ffi`:\n"
" translates a Gleam `Request(BitArray)` into the parameters\n"
" `httpc:request/4` expects, dispatches via the streaming FFI,\n"
" then wraps the response back into a `Response(StreamingBody)`\n"
" so call sites read identically to the buffered transport.\n"
"\n"
" This is the foundational piece for `S3.GetObject` on multi-GB\n"
" objects, event-stream operations (Transcribe, Kinesis), and any\n"
" future S3 transfer manager — none of those can pre-buffer the\n"
" full response into memory.\n"
).
-file("src/aws/internal/http_streaming.gleam", 125).
-spec translate_error(gleam@erlang@atom:atom_()) -> aws@internal@http_send:http_error().
translate_error(Reason) ->
case erlang:atom_to_binary(Reason) of
<<"failed_to_connect"/utf8>> ->
{connect_failed, <<"could not connect to host"/utf8>>};
<<"response_timeout"/utf8>> ->
timeout;
<<"timeout"/utf8>> ->
timeout;
<<"invalid_utf8_response"/utf8>> ->
{invalid_body, <<"response body was not valid UTF-8"/utf8>>};
Other ->
{other, Other}
end.
-file("src/aws/internal/http_streaming.gleam", 118).
-spec to_string_or_empty(bitstring()) -> binary().
to_string_or_empty(B) ->
case gleam@bit_array:to_string(B) of
{ok, S} ->
S;
{error, _} ->
<<""/utf8>>
end.
-file("src/aws/internal/http_streaming.gleam", 110).
-spec list_decode_headers(list({bitstring(), bitstring()})) -> list({binary(),
binary()}).
list_decode_headers(Raw) ->
gleam@list:map(
Raw,
fun(Pair) ->
{to_string_or_empty(erlang:element(1, Pair)),
to_string_or_empty(erlang:element(2, Pair))}
end
).
-file("src/aws/internal/http_streaming.gleam", 78).
-spec send_with(
gleam@http@request:request(bitstring()),
integer(),
boolean(),
boolean()
) -> {ok, gleam@http@response:response(aws@streaming:streaming_body())} |
{error, aws@internal@http_send:http_error()}.
send_with(Req, Timeout_ms, Verify_tls, Http2) ->
Url = begin
_pipe = Req,
_pipe@1 = gleam@http@request:to_uri(_pipe),
gleam@uri:to_string(_pipe@1)
end,
case aws_streaming_ffi:streaming_send(
erlang:element(2, Req),
Url,
erlang:element(3, Req),
erlang:element(4, Req),
Timeout_ms,
Verify_tls,
Http2
) of
{ok, {Status, Headers, Chunks}} ->
{ok,
{response,
Status,
list_decode_headers(Headers),
aws@streaming:from_chunks(Chunks)}};
{error, Reason} ->
{error, translate_error(Reason)}
end.
-file("src/aws/internal/http_streaming.gleam", 31).
?DOC(
" Default streaming sender. Same TLS / timeout defaults as\n"
" `http_send.default_send`; the response body is a `StreamingBody`\n"
" carrying chunks as they arrived on the wire. Pass this as\n"
" `ClientConfig.streaming_http_send` for the SDK runtime, or call\n"
" it directly when wiring custom callers.\n"
).
-spec default_send(gleam@http@request:request(bitstring())) -> {ok,
gleam@http@response:response(aws@streaming:streaming_body())} |
{error, aws@internal@http_send:http_error()}.
default_send(Req) ->
send_with(Req, 30 * 1000, true, false).
-file("src/aws/internal/http_streaming.gleam", 47).
?DOC(
" HTTP/2 variant of `default_send`. Adds `{http_version, \"HTTP/2\"}`\n"
" to the httpc option list; servers that don't speak HTTP/2 negotiate\n"
" down to HTTP/1.1 via ALPN. Use this for endpoints known to benefit:\n"
" S3 multipart uploads, Bedrock streaming responses, Transcribe.\n"
" Caller-facing knob lives at `runtime.with_http2`.\n"
).
-spec default_send_http2(gleam@http@request:request(bitstring())) -> {ok,
gleam@http@response:response(aws@streaming:streaming_body())} |
{error, aws@internal@http_send:http_error()}.
default_send_http2(Req) ->
send_with(Req, 30 * 1000, true, true).
-file("src/aws/internal/http_streaming.gleam", 62).
?DOC(
" Send a `StreamingSend` configurable on timeout and TLS verification.\n"
" Use this for live-tested object-streaming GETs that need either\n"
" fast-fail (IMDS-style 2s timeouts) or extra patience (multi-GB\n"
" downloads).\n"
).
-spec with_timeout_and_tls(integer(), boolean()) -> fun((gleam@http@request:request(bitstring())) -> {ok,
gleam@http@response:response(aws@streaming:streaming_body())} |
{error, aws@internal@http_send:http_error()}).
with_timeout_and_tls(Timeout_ms, Verify_tls) ->
fun(Req) -> send_with(Req, Timeout_ms, Verify_tls, false) end.
-file("src/aws/internal/http_streaming.gleam", 71).
?DOC(
" HTTP/2 + custom timeout / TLS builder. Same as `with_timeout_and_tls`\n"
" but adds the HTTP/2 option to the httpc call.\n"
).
-spec with_timeout_tls_http2(integer(), boolean()) -> fun((gleam@http@request:request(bitstring())) -> {ok,
gleam@http@response:response(aws@streaming:streaming_body())} |
{error, aws@internal@http_send:http_error()}).
with_timeout_tls_http2(Timeout_ms, Verify_tls) ->
fun(Req) -> send_with(Req, Timeout_ms, Verify_tls, true) end.