-module(oaspec@httpc). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/oaspec/httpc.gleam"). -export([config/0, with_timeout/2, build/1, send/1]). -export_type([config/0]). -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( " BEAM HTTP adapter for oaspec generated clients.\n" "\n" " `oaspec/httpc` bridges the pure `oaspec/transport.Send` contract\n" " to `gleam_httpc`. The simplest usage is the bare `send` function:\n" "\n" " ```gleam\n" " import oaspec/httpc\n" " import api/client\n" "\n" " let result = client.list_pets(httpc.send, ...)\n" " ```\n" "\n" " For per-request configuration (timeouts, etc.) use the builder:\n" "\n" " ```gleam\n" " let send =\n" " httpc.config()\n" " |> httpc.with_timeout(5_000)\n" " |> httpc.build\n" " ```\n" ). -opaque config() :: {config, gleam@option:option(integer())}. -file("src/oaspec/httpc.gleam", 40). -spec config() -> config(). config() -> {config, none}. -file("src/oaspec/httpc.gleam", 44). -spec with_timeout(config(), integer()) -> config(). with_timeout(Cfg, Timeout_ms) -> _ = Cfg, {config, {some, Timeout_ms}}. -file("src/oaspec/httpc.gleam", 110). -spec encode_query(list({binary(), binary()})) -> binary(). encode_query(Query) -> case Query of [] -> <<""/utf8>>; _ -> Parts = gleam@list:map( Query, fun(Kv) -> {K, V} = Kv, <<<<(gleam_stdlib:percent_encode(K))/binary, "="/utf8>>/binary, (gleam_stdlib:percent_encode(V))/binary>> end ), <<"?"/utf8, (gleam@string:join(Parts, <<"&"/utf8>>))/binary>> end. -file("src/oaspec/httpc.gleam", 102). -spec build_url(oaspec@transport:request()) -> binary(). build_url(Req) -> Base = case erlang:element(3, Req) of {some, B} -> B; none -> <<""/utf8>> end, <<<>/binary, (encode_query(erlang:element(5, Req)))/binary>>. -file("src/oaspec/httpc.gleam", 124). -spec convert_method(oaspec@transport:method()) -> gleam@http:method(). convert_method(Method) -> case Method of get -> get; post -> post; put -> put; delete -> delete; patch -> patch; head -> head; options -> options; trace -> trace; connect -> connect end. -file("src/oaspec/httpc.gleam", 80). -spec build_http_request(oaspec@transport:request()) -> {ok, gleam@http@request:request(bitstring())} | {error, oaspec@transport:transport_error()}. build_http_request(Req) -> Url = build_url(Req), gleam@result:'try'( begin _pipe = gleam@http@request:to(Url), gleam@result:map_error(_pipe, fun(_) -> {invalid_base_url, Url} end) end, fun(Parsed) -> Parsed@1 = gleam@http@request:set_method( Parsed, convert_method(erlang:element(2, Req)) ), Parsed@2 = gleam@list:fold( erlang:element(6, Req), Parsed@1, fun(R, H) -> {Name, Value} = H, gleam@http@request:set_header(R, Name, Value) end ), Body = case erlang:element(7, Req) of empty_body -> <<>>; {text_body, Text} -> gleam_stdlib:identity(Text); {bytes_body, Bits} -> Bits end, {ok, gleam@http@request:set_body(Parsed@2, Body)} end ). -file("src/oaspec/httpc.gleam", 158). -spec is_text_content_type(binary()) -> boolean(). is_text_content_type(Ct) -> Lowered = string:lowercase(Ct), ((gleam_stdlib:contains_string(Lowered, <<"json"/utf8>>) orelse gleam_stdlib:contains_string( Lowered, <<"xml"/utf8>> )) orelse gleam_stdlib:string_starts_with(Lowered, <<"text/"/utf8>>)) orelse gleam_stdlib:contains_string( Lowered, <<"x-www-form-urlencoded"/utf8>> ). -file("src/oaspec/httpc.gleam", 138). -spec convert_response(gleam@http@response:response(bitstring())) -> oaspec@transport:response(). convert_response(Resp) -> Is_text = case gleam@list:key_find( erlang:element(3, Resp), <<"content-type"/utf8>> ) of {ok, Ct} -> is_text_content_type(Ct); {error, _} -> true end, Body = case Is_text of true -> case gleam@bit_array:to_string(erlang:element(4, Resp)) of {ok, Text} -> {text_body, Text}; {error, _} -> {bytes_body, erlang:element(4, Resp)} end; false -> {bytes_body, erlang:element(4, Resp)} end, {response, erlang:element(2, Resp), erlang:element(3, Resp), Body}. -file("src/oaspec/httpc.gleam", 68). -spec do_send(oaspec@transport:request(), config()) -> {ok, oaspec@transport:response()} | {error, oaspec@transport:transport_error()}. do_send(Req, _) -> gleam@result:'try'( build_http_request(Req), fun(Http_req) -> case gleam@httpc:send_bits(Http_req) of {ok, Resp} -> {ok, convert_response(Resp)}; {error, _} -> {error, {connection_failed, <<"gleam_httpc send failed"/utf8>>}} end end ). -file("src/oaspec/httpc.gleam", 52). ?DOC( " Materialise a `Send` value from a `Config`. Use this when you've\n" " configured timeouts or other options. For the simplest case, prefer\n" " the bare `send` function, which has the same signature as `Send`.\n" ). -spec build(config()) -> fun((oaspec@transport:request()) -> {ok, oaspec@transport:response()} | {error, oaspec@transport:transport_error()}). build(Cfg) -> fun(Req) -> do_send(Req, Cfg) end. -file("src/oaspec/httpc.gleam", 58). ?DOC( " Convenience: equivalent to `config() |> build`. Provides the most\n" " common no-config path as a single function reference.\n" ). -spec send(oaspec@transport:request()) -> {ok, oaspec@transport:response()} | {error, oaspec@transport:transport_error()}. send(Req) -> do_send(Req, config()).